zoukankan      html  css  js  c++  java
  • 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)对使用者的建议:如果你的分页语句耗时太长,又常常只获取前面的部分分页内容,那么就把并行关了吧。至少在微软做出优化之前。





  • 相关阅读:
    Mybatis核心
    正则表达式(二)Java中正则表达式的使用
    Elasticsearch(ES)分词器的那些事儿
    并发编程之:JUC并发控制工具
    scrollTo()和scrollBy()的区别
    SpringBoot 的@Value注解太强大了,用了都说爽!
    SQL 查询并不是从 SELECT 开始的
    jsoup 教程
    爬虫
    case when以及集合聚合函数的用法
  • 原文地址:https://www.cnblogs.com/riskyer/p/3289979.html
Copyright © 2011-2022 走看看