【数据库】教你看懂SQLServer查询语句执行计划

一、 使用SQL执行计划

看SQL语句执行计划有三种方式:①快捷键按Ctrl+L;②选中要执行的SQL然后点击右键,弹出的菜单里面选“显示估计的执行计划”;③按Ctrl+M打开显示执行计划窗口,选择每次执行SQL都会显示出相应的执行计划

二、 查看SQL执行计划

 执行计划的图表是从右向左看的

三、 解读SQL执行计划

SQL Server查找数据记录的几种方式:

1.Table Scan--表扫描(最慢),对表记录逐行进行检查,对于没有索引或者查询条件不走索引时会进行全表扫描;

2.Clustered Index Scan--聚集索引扫描(较慢),按聚集索引对记录逐行进行检查,对有主键/聚集索引的表进行无条件查找或者使用主键/聚集索引过滤;

3.Index Scan--索引扫描(普通),根据索引滤出部分数据在进行逐行检查,;

4.Index Seek--索引查找(较快),根据索引定位记录所在位置再取出记录,建立非聚集索引并把其他显示列加入索引中;

5.Clustered Index Seek--聚集索引查找(最快),直接根据聚集索引获取记录,建立非聚集索引并把其他显示列加入索引中并把聚集索引列当作条件;

6.Key Lookup--书签查找:通过非聚集索引找到所求的行,但这个索引并不包含显示的列,因此还要额外去基本表中找到这些列,所以要进行键查找,如果基本表在堆中则Key Lookup会变成RID查找。

7.RID--书签查找:同上

如果有些SQL执行很慢,可以用执行计划看一下是否包含太多“扫描”操作,可以考虑为这些字段建立索引,建立索引切记不要再经常有更新操作的字段上建立,每次更新数据和插入数据都会导致重建索引的操作,会增加索引的维护成本。

四、数据join方式

在SQL Server中,每个join命令,都会在内部执行时采用这几种更具体的方式来运行: 

1. Nested Loops join:如果一个联接输入很小,而另一个联接输入很大而且已在其联接列上创建了索引, 则索引 Nested Loops 连接是最快的联接操作,因为它们需要的 I/O 和比较都最少。嵌套循环联接也称为“嵌套迭代”,它将一个联接输入用作外部输入表(显示为图形执行计划中的顶端输入),将另一个联接输入用作内部(底端)输入表。外部循环逐行处理外部输入表。内部循环会针对每个外部行执行,在内部输入表中搜索匹配行。最简单的情况是,搜索时扫描整个表或索引;这称为“单纯嵌套循环联接”。如果搜索时使用索引,则称为“索引嵌套循环联接”。如果将索引生成为查询计划的一部分(并在查询完成后立即将索引破坏),则称为“临时索引嵌套循环联接”。

如果外部输入较小而内部输入较大且预先创建了索引,则嵌套循环联接尤其有效。在小事务中(只影响较少数据的事务),索引嵌套循环联接优于合并联接和哈希联接,但在大型查询中,嵌套循环联接通常不是最佳选择。

2. Merge Join:如果两个联接输入并不小但已在二者联接列上排序(例如,如果它们是通过扫描已排序的索引获得的),则合并联接是最快的联接操作。如果两个联接输入都很大,而且这两个输入的大小差不多,则预先排序的合并联接提供的性能与哈希联接相近。但是,如果这两个输入的大小相差很大,则哈希联接操作通常快得多。合并联接要求两个输入都在合并列上排序,而合并列由联接谓词的等效 (ON) 子句定义。通常,查询优化器扫描索引(如果在适当的一组列上存在索引),或在合并联接的下面放一个排序运算符。在极少数情况下,虽然可能有多个等效子句,但只用其中一些可用的等效子句获得合并列。

3. Hash Join:哈希联接可以有效处理未排序的大型非索引输入。它们对复杂查询的中间结果很有用,因为:①.中间结果未经索引(除非已经显式保存到磁盘上然后创建索引),而且通常不为查询计划中的下一个操作进行适当的排序。②.查询优化器只估计中间结果的大小。由于对于复杂查询,估计可能有很大的误差,因此如果中间结果比预期的大得多,则处理中间结果的算法不仅必须有效而且必须适度弱化。哈希联接可以减少使用非规范化。非规范化一般通过减少联接操作获得更好的性能,尽管这样做有冗余之险(如不一致的更新)。哈希联接则减少使用非规范化的需要。哈希联接使垂直分区(用单独的文件或索引代表单个表中的几组列)得以成为物理数据库设计的可行选项。

五、执行过程分析

1.图形的执行计划:

我们将用鼠标点击每个执行计划的节点,可以看到如下数据,各节点的查询数据方式、资源占用情况都可一目了然的看到。

 并且系统会给出缺少索引的提示,我们右键点击即可选择“缺少索引详细信息”,会自动生成创建索引的语句。

2.表格的执行计划:

 输入以下语句来获取表格样式的执行计划

  set statistics profile on 
  
  select *,name from test_index where name='Tom' 
  union  ALL    
  select *,name from test_index where age>=12

如下图,执行查询后,得到二个表格,上面的表格显示了查询的结果,下面的表格显示了查询的执行过程。相比图形方式展示的执行计划, 这种表格可能在展现上不太直观,但是它能反映更多的信息,而且尤其在比较复杂的查询时看起来更容易,因为对于复杂的查询,【执行计划】的步骤太多,图形方式会造成图形过大,不容易观察,需要上下左右不停拖动。

字段解释:
【Rows】:表示在一个执行步骤中,所产生的记录条数。
【Executes】:表示某个执行步骤被执行的次数。
【Stmt Text】:表示要执行的步骤的描述。
【EstimateRows】:表示要预期返回多少行数据。

在这个【执行过程表格】中,对于优化查询来说,前三列是比较重要的。 前二列的数字告诉我们每个步骤所花的成本,对于比较慢的查询中,应该留意它们。 【Stmt Text】告诉我们每个步骤做了什么事情。一行就表示在图形方式下的一个节点。

六、SQL优化

如果不能通过增加索引来解决,那么可以试试调整语句结构,引导SQLServer采用其它的查询方案去执行,一般SQLServer自带的查询优化器会帮你自动优化一部分查询逻辑,此时你要进行SQL重写。 重写的第一要求是:等价转换,重写后查出的数据要和重写前数据保持一直,不能影响业务逻辑。

如何进行SQL重写与优化,可参考https://blog.csdn.net/lm3758/article/details/119842430 

 

 

  • 7
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值