SQLServer2012 分页语句执行分析

上一篇文章提到了,sqlServer2012在使用Offset,Fetch语句分页时,获取了大量不需要的数据,导致查询效率低的问题。

现在让我们来看看,究竟是什么导致sqlServer不能按需取数呢?


1. 先来看看语句,及其执行计划

SELECT BillDate,SUM([QTY]) PosInQty
FROM RtlDetail A,RtlBill B 
WHERE A.billno = B.billno  AND BillDate>='2009-09-25 00:00:00' AND BillDate<='2012-09-25 23:59:59'
GROUP BY BillDate
ORDER BY BillDate
OFFSET 10 ROW FETCH NEXT 20 Rows Only;

耗时:18 s



2. 分析

从执行计划中,可以看到所有的处理都使用了并行处理。

这样就存在一个问题:并行计算时,各处理器如何知道自己处理的部分会有多少条最后出现在结果集中?
如果不知道,就只能各自处理自己的部分,然后汇总起来,再取需要的部分。

从上图的执行计划中可以看出,第一个并行计算,即红框标注的部分是一个RoundRobin的并行任务分配过程,16个核,每个负责从IX_RtlBill_BillDate中取出1/16的数据,进行计算。再看执行计划的分页部分就更清晰一些了,每个并行部分处理完了所有的记录,汇总起来,再通过top方式取得需要的数据部分。



分析至此,认为并行计算在这里拖后腿了。如果没有并行计算,由于在排序列上是有索引的,取数都是按排序的规则进行,那么一旦取得了需要的结果子集,处理就可以结束了。也就可以避免IO及cpu的浪费。


3. 验证一下想法,强制设置最大并行度为1,再执行语句

SELECT BillDate,SUM([QTY]) PosInQty
FROM RtlDetail A,RtlBill B
WHERE A.billno = B.billno  AND BillDate>='2009-09-25 00:00:00' AND BillDate<='2012-09-25 23:59:59'
GROUP BY BillDate
ORDER BY BillDate
OFFSET 10 ROW FETCH NEXT 20 Rows Only option (maxdop 1);

耗时: 1s     (并行时18s秒啊,坑爹啊,有木有。。。)



好的,这个效率终于能和window下的MariaDB媲美了,可人家在Linux下执行只需要 265ms 啊。 呵呵,这个是后话了。


4. 建议

(1)对微软的建议:在生成分页语句的执行计划时,可以先比较下并行的成本和非并行的成本,如果差距太大,就不要用parallel的方式了;

(2)对使用者的建议:如果你的分页语句耗时太长,又常常只获取前面的部分分页内容,那么就把并行关了吧。至少在微软做出优化之前。

相关文章

SELECT a.*,b.dp_name,c.pa_name,fm_name=(CASE WHEN a.fm_n...
if not exists(select name from syscolumns where name=&am...
select a.*,pano=a.pa_no,b.pa_name,f.dp_name,e.fw_state_n...
要在 SQL Server 2019 中设置定时自动重启,可以使用 Window...
您收到的错误消息表明数据库 &#39;EastRiver&#39; 的...
首先我需要查询出需要使用SQL Server Profiler跟踪的数据库标...