如何帮助SQL服务器准备一个更好的计划?

How to help SQL Server prepare a better plan?

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

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

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

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

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

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

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

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