【问题标题】:SQL Stored Procedure Performance Fine on SQL2008 but Awful on SQL2005SQL 存储过程性能在 SQL 2008 上很好,但在 SQL 2005 上很糟糕
【发布时间】:2010-11-17 07:53:14
【问题描述】:

我有一个在运行

编辑 - 我现在注意到,如果我直接在 SQL 2005 上运行 SQL,它会在 ~4 秒内运行,但执行 SP 仍然需要一分钟?看起来问题可能出在 SP 执行中??

CREATE PROCEDURE Workflow.GetTopTasks
    -- Add the parameters for the stored procedure here
    @ownerUserId int,
    @topN int = 10
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    SET ROWCOUNT @topN;

    -- Insert statements for procedure here

WITH cteCalculatedDate (MilestoneDateId, CalculatedMilestoneDate)
AS
(
-- Anchor member definition
    SELECT  md.MilestoneDateId, md.SpecifiedDate
    FROM    Workflow.MilestoneDate md
    WHERE   md.RelativeMilestoneDateId IS NULL
UNION ALL
-- Recursive member definition
    SELECT md.MilestoneDateId, CalculatedMilestoneDate + md.RelativeDays
    FROM    Workflow.MilestoneDate md
            INNER JOIN cteCalculatedDate cte
                on md.RelativeMilestoneDateId = cte.MilestoneDateId
)

-- Statement that executes the CTE

    select 
        we.*
    from Workflow.WorkflowElement we
        left outer join cteCalculatedDate cte
            on cte.MilestoneDateId = we.DueDateId
        inner join Workflow.WorkflowInstance wi
            on wi.WorkflowInstanceId = we.WorkflowInstanceId
        left outer join Workflow.SchemeWorkflow sw
            on sw.WorkflowInstanceId = wi.WorkflowInstanceId
        left outer join Workflow.Scheme s
            on s.SchemeId = sw.SchemeId
        inner join Workflow.WorkflowDefinition wd
            on wd.WorkflowDefinitionId = wi.WorkflowDefinitionId
    where
        we.OwnerId = @ownerUserId           -- for given owner
        and we.CompletedDate is null        -- is not completed
        and we.ElementTypeId <= 4           -- is Action, Data, Decision or Document (Not End, Start or KeyDate)
        and cte.CalculatedMilestoneDate is not null -- has a duedate

    UNION

    select 
        we.*
    from Workflow.WorkflowElement we
        left outer join cteCalculatedDate cte
            on cte.MilestoneDateId = we.DueDateId
        inner join Workflow.WorkflowInstance wi
            on wi.WorkflowInstanceId = we.WorkflowInstanceId
        left outer join Workflow.SchemeWorkflow sw
            on sw.WorkflowInstanceId = wi.WorkflowInstanceId
        left outer join Workflow.Scheme s
            on s.SchemeId = sw.SchemeId
        inner join Workflow.WorkflowDefinition wd
            on wd.WorkflowDefinitionId = wi.WorkflowDefinitionId
    where
        we.OwnerId = @ownerUserId           -- for given owner
        and we.CompletedDate is null        -- is not completed
        and we.ElementTypeId <= 4           -- is Action, Data, Decision or Document (Not End, Start or KeyDate)
        and cte.CalculatedMilestoneDate is null -- does NOT have a duedate

    SET ROWCOUNT 0

END

【问题讨论】:

  • 发布 2008 / 2005 数据库的查询执行计划。这可能有助于更好地了解为什么 2005 变慢

标签: sql sql-server-2005 sql-server-2008


【解决方案1】:

编辑 - 我现在注意到,如果我 直接在 SQL 2005 上运行 SQL 运行约 4 秒,但执行 SP 还需要一分钟吗??

然后是错误的参数嗅探:

http://elegantcode.com/2008/05/17/sql-parameter-sniffing-and-what-to-do-about-it/

SQL poor stored procedure execution plan performance - parameter sniffing

参数嗅探在 2005 年很糟糕,但在 2008 年更好。

【讨论】:

    【解决方案2】:

    您的工会选择CalculatedMilestoneDate 等于NULL 并且 不等于Null。

    这是多余的,只需从 where 子句中删除 CalculatedMilestoneDate 上的条件即可删除整个 UNION。

    除此之外,您应该验证两个数据库是否定义了相同的索引。

    -- Statement that executes the CTE
    
        select 
            we.*
        from Workflow.WorkflowElement we
            left outer join cteCalculatedDate cte
                on cte.MilestoneDateId = we.DueDateId
            inner join Workflow.WorkflowInstance wi
                on wi.WorkflowInstanceId = we.WorkflowInstanceId
            left outer join Workflow.SchemeWorkflow sw
                on sw.WorkflowInstanceId = wi.WorkflowInstanceId
            left outer join Workflow.Scheme s
                on s.SchemeId = sw.SchemeId
            inner join Workflow.WorkflowDefinition wd
                on wd.WorkflowDefinitionId = wi.WorkflowDefinitionId
        where
            we.OwnerId = @ownerUserId           -- for given owner
            and we.CompletedDate is null        -- is not completed
            and we.ElementTypeId <= 4           -- is Action, Data, Decision or Document (Not End, Start or KeyDate)
    

    【讨论】:

    • 联合的原因是我想先获取所有带有 CalculatedMilestoneDate (CMD) 的行,然后再获取没有的行。我希望排序顺序是 CMD 升序,但具有 NULL CMD 的行排在最后而不是排在第一位。我现在已经删除了联合并使用 ISNULL(CMD, '9999-12-31') 添加了一个订单,以确保空值是最后的。谢谢
    • UNION 可能对您有用,但存在一些问题。由于不使用 UNION ALL,您强制 SQL Server 删除重复行(没有任何重复行,但糟糕的 SQL Server 不知道)。如果我没记错的话,删除重复行是通过对两个数据集进行排序和合并来完成的,这是一个耗时的过程。此外,在没有明确指定排序顺序的情况下,返回记录的顺序基本上是任意的,并且可能随着下一个版本或当前版本的更新而改变。您不应该依赖它,而是要具体说明您的排序顺序。
    【解决方案3】:

    如果模式匹配,那么您可能缺少 sql server 2005 实例中的重要索引。尝试运行 sql server 调优顾问并应用其索引建议。

    【讨论】:

    • 我已经在 2008 年恢复了 2005 年的数据库并遇到了这个问题,所以我知道索引是相同的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多