【问题标题】:SQL Server 2012 stored procedure execution times vary wildlySQL Server 2012 存储过程执行时间差异很大
【发布时间】:2015-06-15 14:08:39
【问题描述】:

我有一个只接受 2 个参数的简单存储过程;第一个总是提供,第二个总是通过观察为空,并且只是为了不中断来自应用程序的调用。有一个计划的 SQL 代理任务存储存储过程执行统计信息,然后每周清除缓存的计划。还有每晚计划的作业,使用 Ola Hallegren 的维护程序使用默认参数重建或重组索引。

最近,在清除缓存后,存储过程的执行时间有时会从正常的 2-15 毫秒跳到 120,000 毫秒。对存储过程调用 sp_recompile 会使执行时间恢复正常。根据 SolarWinds DPA(以前称为 Ignite),所有等待时间都是 CPU/内存。

运行 Profiler,我可以复制 Web 应用程序发出的执行调用,将其粘贴到笔记本电脑上运行的 SSMS 中,并在正常的 MS 范围内获得执行时间,而根据 Profiler 的应用程序的持续时间要高得多。从应用程序调用需要 2 分钟的调用将在从应用程序调用完成后的几秒钟内在我的笔记本电脑上在

我希望两次执行都使用相同的缓存计划并产生相同的性能,但显然情况并非如此,因为我从未见过第二个参数的非空值,所以我没有认为这是一个奇怪的调用,包含它可能会缓存一个糟糕的计划。

整个存储过程代码如下。它的唯一目的是返回一个 3 行结果集,指示特定商场是否有任何类型 1 到 3 的当前内容。

 dbo.usp_s_mall_has_rsc_content
    @mall_id        INT,
    @base_tenant_id INT = NULL
AS

SET NOCOUNT ON;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

SELECT  1 AS showcase_item_type_id,
        IIF(EXISTS( SELECT  *
                    FROM    dbo.content_stream_owner AS cso
                            JOIN dbo.content_stream_data AS csd ON csd.content_stream_data_id = cso.content_stream_data_id
                            JOIN dbo.content_stream AS cs ON cs.content_stream_id = csd.content_stream_id
                            JOIN dbo.content_stream_logins AS csl
                                ON (csl.mall_id = cso.mall_id OR csl.base_tenant_id = cso.base_tenant_id)
                    WHERE   cso.mall_id = @mall_id
                            AND (@base_tenant_id IS NULL OR cso.base_tenant_id = @base_tenant_id)
                            AND csd.content_stream_id = 1
                            AND csd.end_dt > SYSDATETIME()
                            AND csd.hidden_flags = 0
                            AND cs.is_active = 1
                            AND csl.is_active = 1), 1, 0) AS has_content
UNION
SELECT  2 , IIF(EXISTS( SELECT  *
                    FROM    dbo.content_stream_owner AS cso
                            JOIN dbo.content_stream_data AS csd ON csd.content_stream_data_id = cso.content_stream_data_id
                            JOIN dbo.content_stream AS cs ON cs.content_stream_id = csd.content_stream_id
                            JOIN dbo.content_stream_logins AS csl
                                ON (csl.mall_id = cso.mall_id OR csl.base_tenant_id = cso.base_tenant_id)
                    WHERE   cso.mall_id = @mall_id
                            AND (@base_tenant_id IS NULL OR cso.base_tenant_id = @base_tenant_id)
                            AND csd.content_stream_id = 2
                            AND csd.end_dt > SYSDATETIME()
                            AND csd.hidden_flags = 0
                            AND cs.is_active = 1
                            AND csl.is_active = 1), 1, 0)
UNION
SELECT  3 , IIF(EXISTS( SELECT  *
                    FROM    dbo.content_stream_owner AS cso
                            JOIN dbo.content_stream_data AS csd ON csd.content_stream_data_id = cso.content_stream_data_id
                            JOIN dbo.content_stream AS cs ON cs.content_stream_id = csd.content_stream_id
                            JOIN dbo.content_stream_logins AS csl
                                ON (csl.mall_id = cso.mall_id OR csl.base_tenant_id = cso.base_tenant_id)
                    WHERE   cso.mall_id = @mall_id
                            AND (@base_tenant_id IS NULL OR cso.base_tenant_id = @base_tenant_id)
                            AND csd.content_stream_id = 3
                            AND csd.end_dt > SYSDATETIME()
                            AND csd.hidden_flags = 0
                            AND cs.is_active = 1
                            AND csl.is_active = 1), 1, 0);

【问题讨论】:

  • 当性能从一个时间变为另一个时,主要是由于 SQL 选择的执行计划不同。重新检查您的索引,使用实际执行计划跟踪运行查询以查看索引是否正确。

标签: caching stored-procedures sql-server-2012


【解决方案1】:

您是否尝试过每次都重新编译存储过程?

ALTER PROCEDURE dbo.usp_s_mall_has_rsc_content
    @mall_id        INT,
    @base_tenant_id INT = NULL
WITH RECOMPILE
AS
...

我在一些存储过程中发现了这个问题。您有嵌套在 IIF(...) 中的查询。 IIF 只需要标量参数,所以不知何故 SQL Server 认为所有涉及的表只给JOIN 1 行并使用低效的LOOP JOIN。一旦表返回几千行以参与联接,它就会爆炸。

【讨论】:

    猜你喜欢
    • 2010-12-04
    • 2010-10-01
    • 2019-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-27
    • 2018-09-01
    相关资源
    最近更新 更多