为啥这个执行计划中的 Sort 算子成本这么高?

Posted

技术标签:

【中文标题】为啥这个执行计划中的 Sort 算子成本这么高?【英文标题】:Why is the cost for the Sort operator in this execution plan so high?为什么这个执行计划中的 Sort 算子成本这么高? 【发布时间】:2021-10-29 16:45:08 【问题描述】:

Sort 运算符表示它只有 100 行要排序。这怎么可能比读取 190 万行更昂贵呢?我一定是读错了或误解了什么。

另外,Sort 运算符中的每次执行的估计行数 怎么只有 100?如果 Index Seek 运算符估计 Number of Rows Per Execution 为 190 万,那么只有 100 行如何通过管道传递给 Sort 运算符?

这里是查询:

    DECLARE @PageIndex INT = 1000;
    DECLARE @PageCount INT  = 1000;

    SELECT  ID
    FROM    dbo.Table1
    WHERE DateCreated >= '2021-10-27'
            AND
        DateCreated < '2021-10-28'
    ORDER BY ID
        OFFSET @PageIndex * @PageCount ROWS FETCH NEXT @PageCount ROWS ONLY 

【问题讨论】:

100 是 估计的 输出行,这是由于来自 OFFSET ... FETCHTOP 的估计效果。它需要在输出之前对它估计为输入的全部 190 万行进行排序。 @MartinSmith 哦,这很有道理。谢谢你。后续问题:为什么只有 100 行?既然我们要取 1000,不应该是 1000 吗? 它不会嗅探变量,因此只会使用硬编码猜测。执行计划是在变量被赋值之前编译的。 该计划经过优化以适应任何@PageCount,而不仅仅是您在此处指定的特定,猜测是100。 Side point:你可能想看看Keyset Pagination,它比你现在做的Row Pagination效率高得多 【参考方案1】:

Sort 运算符(与“Top N Sort”相对)将在返回任何行之前对其 open 方法中的整个输入进行排序。

SQL Server 估计查找将输出 190 万行进入排序。

因此,成本是对 190 万行进行排序。

你在做

OFFSET 1000000 ROWS FETCH NEXT 1000 ROWS ONLY 

排序的实际输出行至少为 1,​​001,000 (maybe more in a parallel plan),TOP 运算符丢弃偏移量的前一百万,然后在收到要返回的 1000 后停止请求行。

100 的估计值只是一个猜测,因为 SQL Server 不知道编译计划时变量在运行时的值。

【讨论】:

以上是关于为啥这个执行计划中的 Sort 算子成本这么高?的主要内容,如果未能解决你的问题,请参考以下文章

除了算子计算成本高吗

为啥这个计数查询这么慢?

与 LINQ 相比,为啥 Array.Sort() 这么慢?

数据库内核分析系列:执行算子探究

halcon算子翻译——return

执行计划中的“查询成本”如何工作?