SQLServer执⾏计划解析
前置说明:
本⽂旨在通过⼀个简单的执⾏计划来引申并总结⼀些SQL Server数据库中的SQL优化的关键点,⽇常总结,其中的概念介绍中有不⾜之处有待补充修改,希望⼤神勘误。SQL语句如下:
SELECT <;所需列> --列太多,不⼀⼀列出
FROM study1
INNER JOIN series1
ON (study1.study_uid_id = series1.study_uid_id) --连接条件1
INNER JOIN image1 image1
ON (series1.series_uid_id = image1.series_uid_id) --连接条件2
where ((study1.user_group &8) != 0) --过滤条件1
and (dality) not in ('PR', 'KO', 'SR', 'AU') --过滤条件2
and study1.study_uid ='xxx' --过滤条件3
order by <;排序列>; --列太多,不⼀⼀列出
第⼀部分:执⾏计划怎么看?
1.从右往左看 + 从上往下看
同⼀⾏的执⾏计划步骤,右边的先执⾏。同⼀列的执⾏步骤,上边的先执⾏。
SQL Server优化器根据统计信息⽣成执⾏计划,由返回⾏数和统计信息直⽅图决定执⾏的先后顺序和表连接⽅式,但是最基本的⼀点:过滤条件先于与连接条件执⾏还是要遵守的。
表连接⽅式包含nested loop,merge join,hash join这三种,三种连接⽅式的区别有兴趣可以bing搜索查看,与Oracle的三种表连接⽅式⼀样,这⾥不再详述。
步骤⼀:根据统计信息发现3个where条件中【过滤条件3】的选择性最好,预估⾏数最少,于是放在执⾏计划最右。由于study_uid是主键,⽆需回表(即⽆需书签查),因此实际上步骤⼀的聚集索引查同时还兼顾了【((study1.user_group &8) != 0)】这个【过滤条件1】。
步骤⼀对应过滤条件1、3。
步骤⼆:这个index seek是根据步骤⼀得到的study_uid_id结合【连接条件1】,对series_index进⾏的索引查,series_index是series表的study_uid_id这列的索引。
步骤三:步骤⼀和步骤⼆通过【连接条件1】进⾏nested loop合成⼀个中间表,这个中间表中有从series_index中拿到的series表的主键值,有了这个主键值我们就可以在步骤四中进⾏针对series的主键键查。
步骤三对应连接条件1。
步骤四:这⼀步的⽬的就是通过步骤三得到的series表主键值,到series的聚集索引中到主键对应的完整的⾏,在完整⾏记录中到对应【过滤条件2】的⾏记录。
步骤四对应过滤条件2。
步骤五:步骤三、四通过nested loop合成⼀个中间表,这⾥的nested loop并不对应某个连接条件,只是纯粹的为了⽣成⼀个中间表。
步骤六:根据步骤五中间表⾥的series_uid_id值到image1表中进⾏索引查,image_index就是image1.series_uid_id列的索引。
步骤七:步骤五、六进⾏nested loop⽣成中间表,这个中间表中含有image1表的主键值,这个主键值是执⾏步骤六时从image_index中拿到的。拿到这主键值我们就可以在步骤⼋中去取到最终我们需要的所有image1表的列了。
步骤七对应连接条件2。
步骤⼋:根据步骤七中间表中的image1主键值,到image1的主键聚集索引中去取我们需要的image1的列数据。
步骤九:步骤七、⼋进⾏nested loop⽣成最后的中间表。
步骤⼗:对步骤九中⽣成的中间表进⾏排序。
最终,我们就取到了需要的、排序好的所有数据。
2.查看每⼀步的详细信息
在出现错误的执⾏计划时,有时我们需要判断为什么优化器选错了执⾏计划,由于选错执⾏计划很有可能导致SQL语句变慢,因此搞清其中的原因是很有必要的。
将⿏标移到每⼀个执⾏计划node,会出现如下图所⽰的详细信息。
我们需要关注的主要有以下⼏点:
物理运算和逻辑运算:
逻辑运算表明了本步骤执⾏计划做了什么,⽽物理运算表明⽤哪种⽅式做的。⼀般物理运算和逻辑运算名字相同,也有例外如Aggregate这种逻辑运算就包含流聚合和哈希匹配两种物理实现⽅式。
1.表连接的物理运算⽅式:
1.嵌套循环
Logical Operation:nested loop
2.哈希连接
Logical Operation:hash join
3.合并连接
Logical Operation:merge join
2.索引访问的物理运算⽅式:
1.索引扫描
Logical Operation:index scan
2.索引查
Logical Operation:index seek
3.聚集索引扫描
Logical Operation:cluster index scan
4.聚集索引查
Logical Operation:cluster index seek
3.表访问的物理运算⽅式:
1.表扫描
Logical Operation:table scan
2.RID查
Logical Operation:RID lookup
sql优化的几种方式3.键查
Logical Operation:key lookup。
(以前的bookmark lookup在SQL Server 2005之后被细分为RID lookup和key loopkup)
##关于RID LOOKUP和KEY LOOKUP的区别,⼀个是⽆主键⼀个是有主键时候出现的,RID LOOKUP的效率不如KEY LOOKUP,因此微软警告表⼀定要有主键##
4.其他的物理运算⽅式:
1.排序
Logical Operation:sort
2.流聚合和哈希匹配
Logical Operation:Aggregate。
在相应排序的流中,计算多组⾏的汇总值。group by⼦句出现时出现,⼀般配合min,max,avg,count,sum等组函数。哈希匹配适⽤于排序量较⼤时,优化器总是选择流聚合和哈希匹配两种物理运算中代价较⼩的⼀种。
3.计算标量
Logical Operation:Compute scalar,count(),avg(),sum()等计算组函数出现时出现,⼀般出现在流聚合物理运算之后,哈希匹配⾃带计算标量功能。
4.并⾏
Logical Operation:Parallel,与并⾏开销阈值和预估的执⾏时间有关。
估计⾏数
根据统计信息估算出的中间表或结果集的⾏数。与最终的运⾏结果记录数⽐较可以推断出统计信息是否失真。
谓词(或seek 谓词,有时两者⼀起出现)
表⽰SQL语句的过滤条件或内部过滤条件。
估计⼦树⼤⼩(即subtree cost和total subtree cost)
这是最为直观的判断执⾏计划是否优良的指标,相当于Oracle的cost,默认情况下totalsubtreecost超过5时SQL Server使⽤并⾏执⾏语句。此外也可以查看每个node的subtreecost来判断哪个步骤消耗最多。
第⼆部分:怎么优化?
SQL Server的优化还是相对简单的,⼤致分为以下⼏种:
1.统计信息失真引起的
更新统计信息即可,⽅便起见应当创建定时更新全库统计信息的作业计划。
2.索引缺失或者索引过多或索引错误引起的
增删索引,或者更改联合索引顺序或者加包含列即可。
多表join时联合索引的存在对性能的提升很⼤,但是要保证有正确的联合索引顺序。
3.语句太烂引起的
类似not in,not exists,like '%xxx%'这些可能引发全表扫描的操作,具体情况具体改写吧......⼳蛾⼦太多列不出来了。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论