You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于SQL执行计划中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

1. 为啥Sort运算符成本比读190万行的Index Seek还高?

SQL Server的执行计划成本可不是按行数多少来拍脑袋算的,它是基于实际资源消耗模型来估算的:

  • 你的Index Seek如果是走DateCreated上的索引,读取190万行其实是很高效的——毕竟索引是有序存储的,属于顺序IO,成本被估算得很低。
  • 但Sort就不一样了:你这查询要OFFSET 1000000 ROWS,意味着SQL Server得先把所有符合日期条件的190万行全量排序,然后再跳过前100万行取后面的1000行。Sort的成本主要看内存够不够用:如果排序的数据量超过了SQL Server分配的内存配额,就会触发磁盘溢出排序——把数据写到tempdb的磁盘上,这可比内存排序慢太多了,CPU和IO成本直接飙升。哪怕执行计划显示“仅排序100行”,那也是指Sort最终输出的行数,不是它实际处理的190万行,这才是成本高的核心原因。

2. 为啥Index Seek返回190万行,却只有100行传到Sort?

这大概率是你对执行计划的解读偏差了:

  • 执行计划里运算符的“每执行估算行数”,对于Sort来说,显示的是它最终输出到下一个步骤的行数(也就是你FETCH的1000行,你说的100可能是估算错误,或者看错数字啦),而不是它接收的输入行数。你可以看看运算符之间的箭头粗细——从Index Seek到Sort的箭头应该是很粗的,对应实际传递的190万行。
  • 另外,这么大的偏移量(100万),SQL Server没法用Top N Sort优化(那种只排序前N行的操作),必须先全量排序所有符合条件的行,所以Sort的输入肯定是190万行,没跑。

3. Sort的每执行估算行数为啥只有100?

这是基数估算偏差搞的鬼:

  • 你用了变量@PageIndex和@PageCount,SQL Server在编译查询的时候不知道这些变量的具体值,只能用默认的基数规则来估算,结果就不准了——它可能错误估算了OFFSET后的输出行数。
  • 你可以试试把变量换成常量(比如直接写OFFSET 1000000 ROWS)再看执行计划,这时候基数估算会准确很多,Sort的输出行数应该会显示1000,而不是100。

给你个优化小建议

这种大偏移量的分页查询性能本来就差,因为要全量排序。你可以试试创建一个按ID排序的覆盖索引:

CREATE NONCLUSTERED INDEX IX_Table1_ID_DateCreated ON dbo.Table1 (ID) INCLUDE (DateCreated)

然后改写查询,先找到符合日期条件的ID范围,再利用ID的有序性来分页,这样就能避免全量排序,性能会提升很多。

内容的提问来源于stack exchange,提问作者Evan Payne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 23:23:14