前置说明:
本文旨在通过一个简单的执行计划来引申并总结一些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 (series1.modality) 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
        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%'这些可能引发全表扫描的操作,具体情况具体改写吧......幺蛾子太多列不出来了。

SQL Server 执行计划解析的更多相关文章

  1. SQL Server 执行计划缓存

    标签:SQL SERVER/MSSQL SERVER/数据库/DBA/内存池/缓冲区 概述 了解执行计划对数据库性能分析很重要,其中涉及到了语句性能分析与存储,这也是写这篇文章的目的,在了解执行计划之 ...

  2. sql server 执行计划(execution plan)介绍

    大纲:目的介绍sql server 中执行计划的大致使用,当遇到查询性能瓶颈时,可以发挥用处,而且带有比较详细的学习文档和计划,阅读者可以按照我计划进行,从而达到对执行计划一个比较系统的学习. 什么是 ...

  3. SQL Server 执行计划中的扫描方式举例说明

    SQL Server 执行计划中的扫描方式举例说明 原文地址:http://www.cnblogs.com/zihunqingxin/p/3201155.html 1.执行计划使用方式 选中需要执行的 ...

  4. SQL Server执行计划那些事儿(3)——书签查找

    接下来的文章是记录自己曾经的盲点,同时也透漏了自己的发展历程(可能发展也算不上,只能说是瞎混).当然,一些盲点也在工作和探究过程中慢慢有些眉目,现在也愿意发扬博客园的奉献精神,拿出来和大家分享一下. ...

  5. SQL Server执行计划那些事儿(2)——查找和扫描

    接下来的文章是记录自己曾经的盲点,同时也透漏了自己的发展历程(可能发展也算不上,只能说是瞎混).当然,一些盲点也在工作和探究过程中慢慢有些眉目,现在也愿意发扬博客园的奉献精神,拿出来和大家分享一下. ...

  6. 引用:初探Sql Server 执行计划及Sql查询优化

    原文:引用:初探Sql Server 执行计划及Sql查询优化 初探Sql Server 执行计划及Sql查询优化 收藏 MSSQL优化之————探索MSSQL执行计划 作者:no_mIss 最近总想 ...

  7. SQL Server 执行计划操作符详解(3)——计算标量(Compute Scalar)

    接上文:SQL Server 执行计划操作符详解(2)--串联(Concatenation ) 前言: 前面两篇文章介绍了关于串联(Concatenation)和断言(Assert)操作符,本文介绍第 ...

  8. SQL Server 执行计划操作符详解(2)——串联(Concatenation )

    本文接上文:SQL Server 执行计划操作符详解(1)--断言(Assert) 前言: 根据计划,本文开始讲述另外一个操作符串联(Concatenation),读者可以根据这个词(中英文均可)先幻 ...

  9. 浅析SQL SERVER执行计划中的各类怪相

    在查看执行计划或调优过程中,执行计划里面有些现象总会让人有些疑惑不解: 1:为什么同一条SQL语句有时候会走索引查找,有时候SQL脚本又不走索引查找,反而走全表扫描? 2:同一条SQL语句,查询条件的 ...

随机推荐

  1. springboot情操陶冶-SpringApplication(一)

    SpringApplication是所有springboot的入口类,分析此类有助于我们了解springboot的工作机制.本文以2.0.3.REALEASE版本作分析 SpringApplicati ...

  2. Deep learning with Python 学习笔记(11)

    总结 机器学习(machine learning)是人工智能的一个特殊子领域,其目标是仅靠观察训练数据来自动开发程序[即模型(model)].将数据转换为程序的这个过程叫作学习(learning) 深 ...

  3. Spring Cloud Stream消费失败后的处理策略(四):重新入队(RabbitMQ)

    应用场景 之前我们已经通过<Spring Cloud Stream消费失败后的处理策略(一):自动重试>一文介绍了Spring Cloud Stream默认的消息重试功能.本文将介绍Rab ...

  4. SQL Server 本地数据库登录不上 解决方法

    sql本地数据库登录不了的话.先看看自己计算机 服务 SQL server  (MSSQLSERVER)  没有打开的话,请打开. 今天说的情景模式是  你误删了windows登录:禁用了sa登录:s ...

  5. ASP.NET MVC 学习笔记-7.自定义配置信息(后续)

    自定义配置信息的高级应用 通过上篇博文对简单的自定义配置信息的学习,使得更加灵活的控制系统配置信息.实际项目中,这种配置的灵活度往往无法满足项目的灵活度和扩展性. 比如,一个配置信息有三部分组成,而每 ...

  6. .NET MVC JSON JavaScriptSerializer 字符串的长度超过 maxJsonLength 值问题的解决

    [ArgumentException: 使用 JSON JavaScriptSerializer 序列化或还原序列化期间发生错误.字符串的长度超过在 maxJsonLength 属性上设定的值. 参数 ...

  7. (5)Microsoft office Word 2013版本操作入门_标尺

    1.标尺 :左缩进,右缩进,悬挂缩进,首行缩进,阴影部分 可以左右拖拽调整边缘. 1.1  左缩进:默认缩进所在的段落,要缩进多段则需要多段落选中, 后拖动左缩进. 1.2 首行缩进缩进或者突出所选的 ...

  8. myeclipse无法部署项目的解决

    一.问题 myeclipse无法部署项目,点击这个部署按钮没有反应. 二.解决办法 1.找到myeclipse的工作空间,也就是启动时的那个项目保存的空间,我的是在D:\myeclipse_works ...

  9. Java8新特性-Lambda表达式是什么?

    目录 前言 匿名内部类 函数式接口 和 Lambda表达式语法 实现函数式接口并使用Lambda表达式: 所以Lambda表达式是什么? 实战应用 总结 前言 Java8新特性-Lambda表达式,好 ...

  10. 写一个可插入自定义标签的 Textarea 组件

    - “插入自定义标签是什么鬼?” - “比如你要插入一个<wise></wise>的标签...” - “什么情况下会有这种需求?” - “得罪了产品的情况下...” 一.需求背 ...