如何帮助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 进行查找(超过一百万次),可以添加到正在扫描的索引。
有时我在 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 进行查找(超过一百万次),可以添加到正在扫描的索引。