操作符导致 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 成功地消除了这个警告。

以下是我目前尝试过的:

任何人都可以帮助我摆脱这个警告吗?如果您需要我提供其他信息,请随时告诉我。

注意:我找到了一种可能的解决方案,可以在 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 关系,这会增大结果大小,并使最终结果大小难以预测(导致溢出)。

所以这是重新考虑此查询的情况。也许你可以在服务器上聚合它而不是将所有结果发送给客户端,或者将它分解成多个查询这样你就不必排序和发送 ActvtyPmnt 的笛卡尔积每个 Rqst。如果 Rqst 有 50 个 Actvty 和 4 个 Pmnt,查询将为那个 Rqst.

return 200 行

此外,它无缘无故多次加入 Pmnt,这无济于事。