|
我是这么理解这2个SQL的执行过程的:
SQL1是先通过inner join找出所有匹配的行(有个笛卡儿乘积过程),然后再做GROUP BY工作,由于内连接是通过PK进行关联的,因此2个表都能用到索引来扫描表。
SQL2是对作为a表的T1进行基于索引的扫描,每扫描一条记录是由于存在子查询,所以还要到子查询中去对T1表进行进一步的扫描,扫描的范围是id号小于等于a表id号的记录,把这些记录的zl字段进行累计。然后接着扫描a表的下一条记录。
经过不断的测试(a.id=6000、10000、15000、20000、25000、30000),
记录范围|6000、10000、15000、20000、25000、30000
----|----------------------
SQL1:-| 01:42、03:40、08:18、07:40、11:47、超过25分钟被我中断
SQL2:-| 00:35、01:31、03:26、06:13、09:37、13:40
----------------------------时间:分:秒(mm:ss)
事实证明SQL2的性能的确要高于SQL1,那么究竟是什么环节让SQL1的性能如此差
我分别查看2个SQL的执行计划图,发现以下几处区别:
1、看到最大的区别就在Nested Loops操作上,SQL1涉及的行在记录范围为30000的时候竟然达到了449M行也就是4亿多行,真是个天文数字,不慢才怪呢。
2、SQL2对表的检索都是扫描非聚集索引中的特定范围的行,使用了Index Seek,估计涉及29999行记录;而SQL1对表的检索是扫描聚集索引,使用的是Index Sacan,估计涉及99354行记录。
3、SQL1在做Hash Match/Partial Aggregate操作的时候估计涉及的行是12万行记录,并且在接下来的Parallelism操作中涉及的行数依然是12万;而SQL2在Compute Scalar、Stream Aggregate等操作中涉及的行数最多也就是29999。
从以上3点看,SQL2的执行效率高于SQL2也是在情理之中的。 |
|