SQLServer2012分页语句执行分析
sqlserver2012分页语句执行分析
现在让我们来看看,究竟是什么导致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)对使用者的建议:如果你的分页语句耗时太长,又常常只获取前面的部分分页内容,那么就把并行关了吧。至少在微软做出优化之前。
下一篇: json的使用小结
推荐阅读
-
详解MySQL的limit用法和分页查询语句的性能分析
-
SQLServer2012分页语句执行分析
-
Laravel框架执行原生SQL语句及使用paginate分页的方法
-
Mybaits 源码解析 (六)----- 全网最详细:Select 语句的执行过程分析(上篇)(Mapper方法是如何调用到XML中的SQL的?)
-
oracle导出sql语句的结果集和保存执行的sql语句(深入分析)
-
获取django框架orm query执行的sql语句实现方法分析
-
MyBatis MapperProvider MessageFormat拼接批量SQL语句执行报错的原因分析及解决办法
-
sql和MySQL的语句执行顺序分析
-
通过10046分析SQL语句的执行计划、等待事件
-
详细分析SQL语句逻辑执行过程和相关语法