操作符导致 tempdb 溢出数据
Operator causing tempdb to spill data
我有以下查询,它导致排序运算符溢出 tempdb 中的数据,这很可能是导致我面临的性能问题的原因。
SELECT
P_All.Status, P_All.Date, P_All.Year, P_All.Amount, P_All.ID,
P.ID,
A.ID, A.Type_ID, A.Date, A.Amount,
R.Year, R.Amount, R.Balance, R.Title, R.TOTAL, R.TYPE, R.Date, R.ID,
O.TYPE, O.Name, O.CITY,
D.City, D.Code, D.Zip, D.Address,
S.Description,
FROM
Pmnt P INNER JOIN Rqst R ON P.Rqst_ID=R.ID
INNER JOIN Org O ON R.Org_ID=O.ID
INNER JOIN Pmnt P_All ON R.ID=P_All.Rqst_ID
LEFT OUTER JOIN Actvty A ON R.ID=A.Rqst_ID
INNER JOIN Addrs D ON O.Addrs_ID=D.ID
INNER JOIN Sts S ON O.Sts_ID=Sts.ID
WHERE
R.TYPE=N'INITIAL' AND R.Date<{ts '2021-08-13 00:00:00'}
ORDER BY
O.TYPE, R.ID
我已经尝试了一些我在 google 上找到的东西,但其中 none 成功地消除了这个警告。
以下是我目前尝试过的:
- 使用
Exec sp_updatestats
和 UPDATE STATISTICS Org with fullscan
更新了统计数据(对于以上所有 6 个表格)。
- 为所有 6 个表创建了涉及此查询中涉及的所有列的索引。 (我对索引很陌生)
任何人都可以帮助我摆脱这个警告吗?如果您需要我提供其他信息,请随时告诉我。
注意:我找到了一种可能的解决方案,可以在 this article 中将数据库的兼容性级别更新为 150
,但我担心如果更改它可能会搞砸某物。所以,现在我正在寻找一些与索引或查询优化相关的解决方案。
实际SQL查询执行计划-https://www.brentozar.com/pastetheplan/?id=HJxdkN4et
you really don't need all those parentheses in your FROM
这实际上是一条线索。这表明原作者是使用图形查询设计器的菜鸟,所以你应该怀疑这个查询有问题,事实证明确实如此。
以下是计划中的查询等待和执行统计信息:
<WaitStats>
<Wait WaitType="MEMORY_ALLOCATION_EXT" WaitTimeMs="18" WaitCount="7171" />
<Wait WaitType="RESERVED_MEMORY_ALLOCATION_EXT" WaitTimeMs="61" WaitCount="64279" />
<Wait WaitType="SOS_SCHEDULER_YIELD" WaitTimeMs="358" WaitCount="3705" />
<Wait WaitType="LATCH_EX" WaitTimeMs="810" WaitCount="149" />
<Wait WaitType="IO_COMPLETION" WaitTimeMs="38588" WaitCount="10990" />
<Wait WaitType="ASYNC_NETWORK_IO" WaitTimeMs="117148" WaitCount="1530" />
<Wait WaitType="CXPACKET" WaitTimeMs="558490" WaitCount="39296" />
</WaitStats>
<QueryTimeStats CpuTime="54137" ElapsedTime="156188" />
在经过的 156 秒中,有 117 秒正在等待向客户端发送 420 万行。 Activity 只有 200K 行,其余表很小,不到 100k 行。
但它连接了多个 1-many 关系,这会增大结果大小,并使最终结果大小难以预测(导致溢出)。
所以这是重新考虑此查询的情况。也许你可以在服务器上聚合它而不是将所有结果发送给客户端,或者将它分解成多个查询这样你就不必排序和发送 Actvty
和 Pmnt
的笛卡尔积每个 Rqst
。如果 Rqst
有 50 个 Actvty
和 4 个 Pmnt
,查询将为那个 Rqst
.
return 200 行
此外,它无缘无故多次加入 Pmnt
,这无济于事。
我有以下查询,它导致排序运算符溢出 tempdb 中的数据,这很可能是导致我面临的性能问题的原因。
SELECT
P_All.Status, P_All.Date, P_All.Year, P_All.Amount, P_All.ID,
P.ID,
A.ID, A.Type_ID, A.Date, A.Amount,
R.Year, R.Amount, R.Balance, R.Title, R.TOTAL, R.TYPE, R.Date, R.ID,
O.TYPE, O.Name, O.CITY,
D.City, D.Code, D.Zip, D.Address,
S.Description,
FROM
Pmnt P INNER JOIN Rqst R ON P.Rqst_ID=R.ID
INNER JOIN Org O ON R.Org_ID=O.ID
INNER JOIN Pmnt P_All ON R.ID=P_All.Rqst_ID
LEFT OUTER JOIN Actvty A ON R.ID=A.Rqst_ID
INNER JOIN Addrs D ON O.Addrs_ID=D.ID
INNER JOIN Sts S ON O.Sts_ID=Sts.ID
WHERE
R.TYPE=N'INITIAL' AND R.Date<{ts '2021-08-13 00:00:00'}
ORDER BY
O.TYPE, R.ID
我已经尝试了一些我在 google 上找到的东西,但其中 none 成功地消除了这个警告。
以下是我目前尝试过的:
- 使用
Exec sp_updatestats
和UPDATE STATISTICS Org with fullscan
更新了统计数据(对于以上所有 6 个表格)。 - 为所有 6 个表创建了涉及此查询中涉及的所有列的索引。 (我对索引很陌生)
任何人都可以帮助我摆脱这个警告吗?如果您需要我提供其他信息,请随时告诉我。
注意:我找到了一种可能的解决方案,可以在 this article 中将数据库的兼容性级别更新为 150
,但我担心如果更改它可能会搞砸某物。所以,现在我正在寻找一些与索引或查询优化相关的解决方案。
实际SQL查询执行计划-https://www.brentozar.com/pastetheplan/?id=HJxdkN4et
you really don't need all those parentheses in your FROM
这实际上是一条线索。这表明原作者是使用图形查询设计器的菜鸟,所以你应该怀疑这个查询有问题,事实证明确实如此。
以下是计划中的查询等待和执行统计信息:
<WaitStats>
<Wait WaitType="MEMORY_ALLOCATION_EXT" WaitTimeMs="18" WaitCount="7171" />
<Wait WaitType="RESERVED_MEMORY_ALLOCATION_EXT" WaitTimeMs="61" WaitCount="64279" />
<Wait WaitType="SOS_SCHEDULER_YIELD" WaitTimeMs="358" WaitCount="3705" />
<Wait WaitType="LATCH_EX" WaitTimeMs="810" WaitCount="149" />
<Wait WaitType="IO_COMPLETION" WaitTimeMs="38588" WaitCount="10990" />
<Wait WaitType="ASYNC_NETWORK_IO" WaitTimeMs="117148" WaitCount="1530" />
<Wait WaitType="CXPACKET" WaitTimeMs="558490" WaitCount="39296" />
</WaitStats>
<QueryTimeStats CpuTime="54137" ElapsedTime="156188" />
在经过的 156 秒中,有 117 秒正在等待向客户端发送 420 万行。 Activity 只有 200K 行,其余表很小,不到 100k 行。
但它连接了多个 1-many 关系,这会增大结果大小,并使最终结果大小难以预测(导致溢出)。
所以这是重新考虑此查询的情况。也许你可以在服务器上聚合它而不是将所有结果发送给客户端,或者将它分解成多个查询这样你就不必排序和发送 Actvty
和 Pmnt
的笛卡尔积每个 Rqst
。如果 Rqst
有 50 个 Actvty
和 4 个 Pmnt
,查询将为那个 Rqst
.
此外,它无缘无故多次加入 Pmnt
,这无济于事。