如何帮助 SQL Server 制定更好的计划?

Posted

技术标签:

【中文标题】如何帮助 SQL Server 制定更好的计划?【英文标题】:How to help SQL Server prepare a better plan? 【发布时间】:2019-05-17 16:05:33 【问题描述】:

有时我在 SQL Server 中的查询需要几分钟,而再次运行它只需要几分之一秒。我假设查询优化器第一次做出了错误的决定,但收集到的数据让它下次做得更好。查看查询计划,我有时会看到这样的内容:

我认为这意味着优化器计算错误的行数并做出了错误的决定,例如如何加入。我该如何“帮助”它?提供提示?更新统计数据?添加索引?重写查询?

这里有更多关于查询部分的信息(如您所见,已经有一个聚集索引):

更新:这是查询(为简洁起见被截断):

WITH session_temp AS 
(
    SELECT 
        SESSION_N, SESSION_DATE, SESSION_CREATE_DATE, MASTER_SESSION_N, ROOT_SESSION_N  
    FROM 
        T_SESSION 
    WHERE 
        PATIENT_N = 140945 AND SESSION_ACTIVE_FLAG = 1
)
SELECT  
    S.SESSION_DATE, S.SESSION_CREATE_DATE, 
    SUB_ST.SESSION_N, SUB_ST.XML_VALUE, 'subtemplate' AS SOURCE_TYPE 
FROM 
    session_temp SUB_S 
INNER LOOP JOIN 
    T_SESSION_TEMPLATE SUB_ST ON (SUB_S.SESSION_N = SUB_ST.SESSION_N AND SUB_S.MASTER_SESSION_N IS NOT NULL) 
JOIN
    T_SESSION_TEMPLATE ST ON (SUB_S.ROOT_SESSION_N = ST.SESSION_N) 
JOIN
    session_temp S ON ST.SESSION_N = S.SESSION_N 
JOIN
    T_SESSION_CATEGORY SC ON S.SESSION_N = SC.SESSION_N
WHERE 
    ST.TEMPLATE_N IN (1709, 1686, 1660, 1526, 1474, 1456, 1301, 1258) 
    AND SUB_ST.TEMPLATE_N IN (617) 
    AND SUB_S.MASTER_SESSION_N IS NOT NULL 
    AND S.MASTER_SESSION_N IS NULL 
    AND SC.category_n IN (241, 119, 181, 183, 110)
                        
UNION ALL

SELECT  
    SESSION_DATE, SESSION_CREATE_DATE, ST.SESSION_N, XML_VALUE, 
    'include' AS SOURCE_TYPE
FROM 
    T_SESSION_TEMPLATE ST 
JOIN  
    session_temp S ON ST.SESSION_N = S.SESSION_N
WHERE 
    ST.TEMPLATE_N IN (1709, 1686, 1660, 1526, 1474, 1456, 1301, 1258) 
    AND S.MASTER_SESSION_N IS NULL
ORDER BY 
    SESSION_DATE DESC, SESSION_N DESC 

更新 2:执行计划如下:https://www.brentozar.com/pastetheplan/?id=BJL7Bwh3V

【问题讨论】:

发布您的查询,实际执行计划 (Paste the Plan) 将在这里有所帮助;没有它,我们只能猜测。我在黑暗中刺伤:你没有使用表变量是吗? 看准了!表变量看起来比使用临时表更好 你的问题; SQL Server(2017 除外)假定表变量包含 1 行。 Paste the Plan 版本中的 IN 很大。在那里使用查找表可能会更好。 尝试将 XML_VALUE 添加到索引:IX_T_SESSION_TEMPLATE_SESSION_N。这应该可以防止导致大部分 IO 的密钥查找。 【参考方案1】:

尝试将 XML_VALUE 添加到索引:IX_T_SESSION_TEMPLATE_SESSION_N。这应该可以防止导致大部分 IO 的密钥查找。

在您的执行计划中,您正在查看此部分:

如果您将鼠标悬停在 Key Lookup 运算符上(估计为 97%),您可以看到它必须对 XML_VALUE 进行查找(超过一百万次),可以将其添加到正在扫描的索引中。

【讨论】:

以上是关于如何帮助 SQL Server 制定更好的计划?的主要内容,如果未能解决你的问题,请参考以下文章

制定PMP项目管理计划有啥更好的方法?

在 SQL Server 的维护计划中添加 T-SQL

您的 SQL Server 备份/维护计划是啥?

执行真实计划 SQL Server

Explain 执行计划 和 SQL优化

SQL Server 索引如何帮助将 BETWEEN 用于给定查询