当前位置:Gxlcms > 数据库问题 > SQL Server SQL性能优化之--通过拆分SQL提高执行效率,以及性能高低背后的原因

SQL Server SQL性能优化之--通过拆分SQL提高执行效率,以及性能高低背后的原因

时间:2021-07-01 10:21:17 帮助过:32人阅读

select A.colName,B.colName,C.colName,D.colName
from TableA A
     inner join TableB B on A.Id=B.Id and A.Type=B.Type and 其它条件
     inner join TableC C on B.Code=C.Code and 其它条件
     inner join TableD D on C.BusinessId=D.BusinessId and 其它条件
where A.BusinessDate>=Date1
      and A.BusinessDate<=Date2
      and A.BusinessStatus=‘‘
      and B.BusinessDate=‘‘
      and C.BusinessDate=‘‘
      and 其他查询条件
      and 其他查询条件 order by col1,col2,col3
OFFSET M ROWS FETCH NEXT N ROWS ONLY
技术分享

如果是三个表拆分,跟第四个表join,可以通过如下备选方案 可以把ABC join起来加上对应的查询条件,拆分成一个临时表,然后跟D表join, 可以把ABD join起来加上对应的查询条件,拆分成一个临时表,然后跟C表join, 可以把ACD join起来加上对应的查询条件,拆分成一个临时表,然后跟B表join, 可以把BCD join起来加上对应的查询条件,拆分成一个临时表,然后跟A表join, 这里就有一个小技巧,要观察一下三个表加上对应的查询条件结果集的总行数, 比如ABC join是3000条结果集,这3000条结果集跟D表join产生了20w条结果,那么就可以先排除D表, 让ABC join起来加上对应的查询条件,生成临时表,在临时表上建立合理的索引,再跟D表join 也就是说先排除一些产生大结果集的join参与join,其他的表join,得到一个相对较少的临时结果集, 在临时结果集上建立索引,再用这个临时结果集去join其他的表。

这种拆分方式,还有最重要的一步,在临时表上加合适的索引,以最优化临时表与物理表的执行 如果数据量不大,拆分是适得其反的,完全没有必要,但是在数据量越大的时候,效果越明显, 那么这里的拆分后究竟有多明显的效果? 记得之前是多少秒?1分钟3秒,也就是63秒,这里是2秒钟 说实话,这种拆分方式经常用,说实话这个速度的提示是我没有想到的

技术分享

 

 

 

其实问题到这里才刚刚开始

  为什么拆分之前那么慢,为什么拆分之后又变得这么快?   执行计划就不细看了,上文说了,这个查询并不缺少索引,也确实用到了索引,但是并不代表,有了索引,用到了索引,就万事大吉了。   因为查询条件较为复杂,相关的表建立的是复合索引,如果要说索引,就必须说统计信息(statistics),   对于复合索引,也即两个以上字段的索引,其统计信息的特点是只会维护第一个字段的直方图信息,   这就决定了SQL Sever在对数据量做预估的时候,有可能出现误差   我这里有写统计信息相关的知识的,可以参考   某些多个查询条件的情况下,即便是用到了复合索引,   SQL Server并不能准确地预估某些条件下数据的行数,如果SQL Server一开始就错误地预测到预期的数据量很小,   那么后继每一步都无法准确地预测真正数据的大小,也即第一步就错了,导致后面每一步都受到第一步的干扰,   后面往往会采用Loop join的方式执行,这种方式对于较小的结果集,当然没有问题,如果遇到较大的结果集,就非常低效了   (见过很多超级复杂,join的表多,很复杂的查询条件,且运行缓慢的SQL,SQL Server往往是以loop join的方式去处理表之间)

技术分享

  所以我们先拆分出来一个较小的结果集,存放在临时表,   在第一步的拆分过程中,即便某些情况下无法正确地预估表的行数,因为结果集比较小,采用了Loop join的方式来处理也是没有问题的。   一旦我们拆分出来一个临时表,对临时表加上合理的索引,再跟其他的大表join,   由于SQL变得简单了,加上有索引,往往会以高效的方式去执行,性能也就上去了   那么什么是高效?是不是主观臆断或者说是猜测,比如呢?   比如通过更大的内存授予(Memory Grant),因为能更加准确地预估到每一步的行数吧,采用并行运行(这里有写并行相关的,可参考)等等,获取更多的资源从而提高执行效率   事实上,本文举例的SQL拆分之后的运行,正式因为此,授予更大的内存+并行,才得以高效执行。如图。

  技术分享

 

总结:

  本文通过一个SQL语句的拆分来达到优化的方法,说明在一定情况下,拆分SQL是优化的可选方案。   当然也不是说,复杂的SQL一定会执行的慢,一定需要拆分,对于多个大表join,如果逻辑简单,可能也会快速的执行   但是对于那些多个大表join的SQL,尤其是在连接条件,查询条件,索引信息复杂的情况下,如果出现性能问题,可以考虑通过拆分SQL来优化其执行效率   这个只能说,执行的慢的SQL,通过具体的分析,是可以通过拆分SQL语句生成临时表来解决的。   SQL 拆分解决了性能问题,但,更重要的是,一定要弄明白:慢,是为什么慢,快,是为什么快,弄不清楚的话,类似问题还会时不时地让你感到困惑。   理解了本质,才能够游刃有余,更好地掌握SQL Server。

SQL Server SQL性能优化之--通过拆分SQL提高执行效率,以及性能高低背后的原因

标签:tle   问题:   哈哈   fse   分页   运行   开发人员   fetch   提示   

人气教程排行