听到大牛们说执行计划,总是很惶恐,是对知识的缺乏的惶恐,所以必须得学习执行计划,以减少对这一块知识的惶恐,下面是对执行计划的第一讲-理解执行计划。

本系列【T-SQL】主要是针对T-SQL的总结。

一、为什么需要执行计划?

(1)帮助分析

当我们想要去分析SQL语句存在很慢时,需要有一个分析工具帮助我们分析SQL语句中哪些地方存在性能问题,而这个分析工具就是执行计划,看懂执行计划就能知道哪些地方有性能问题,然后结合自己已有的SQL知识分析为什么这些地方有性能问题,进而尝试提出解决方案,并测试自己的方案是否能提高性能,以及方案是否合理。

(2)获取其他信息

a.哪些索引被用在查询中

b.数据是怎样关联起来的

c.数据是怎样检索的

d.为什么SQL Server没有使用这些索引

e.SQL语句的执行顺序

二、什么是执行计划?

SQL语句执行之前,需要有一个执行的方案,而这个方案是由查询优化器(查询分析器)产生的,并且是高效的、开销最小的方案,这就是执行计划。不知道查询优化器的可以看我写之前写的一篇博客:

【T-SQL进阶】02.理解SQL查询的底层原理

三、如何显示执行计划?

执行计划有三种格式:图形化执行计划,文本化执行计划,XML格式的执行计划。

(1)图形化执行计划

优点:可视性好。

a.估计的执行计划

可以通过鼠标点击图标显示估计的执行计划或者通过快捷键Ctrl+L显示估计执行计划。预估执行计划不会真正执行,只是预估出来的执行计划。

b.实际的执行计划

单击实际的执行计划图标,该图标处于选中状态,然后执行SQL语句,将会显示实际执行的执行计划。

(2)文本化执行计划

用独立的行来代表每一个迭代器。使用竖线(符号“|”)来代表查询树中迭代器之间的父子关系。数据都是从子迭代器流向父迭代器。

优点:和图形计划比较,文本执行计划更容易保存、处理、搜索和比较。

--显示完整的预估执行计划信息
SET SHOWPLAN_TEXT ON
GO
--显示预估执行计划的有限信息,可以用osql.exe等工具分析
SET SHOWPLAN_ALL ON
GO
--显示完整的实际执行计划信息
SET STATISTICS PROFILE ON
GO

总结:

(3)XML执行计划

优点:三种执行计划中最详细的。图形执行计划可以保存为扩展名为.sqlplan的XML格式的计划文件,打开此文件将会以图形化的执行计划展示。

--显示预估执行计划
SET SHOWPLAN_XML ON
GO
--显示实际计划的XML格式数据
SET STATISTICS XML ON
GO

总结

四、如何分析执行计划?

下面分析三种情况的执行计划:

1.堆表

2.聚集索引

3.非聚集索引

结构 扫描 查找 书签查找
堆表 表扫描 没有这种情况 RID 查找
聚集索引 聚集索引扫描 聚集索引查找 没有这种情况
非聚集索引 如果用到了索引,则是索引扫描 索引查找 Key 查找

关于表扫描的那些事:

  • 没有索引的表称作堆表,查找匹配行用的是表扫描。
  • 如果出现表扫描操作,则证明这个表上一定没有聚集索引。

关于索引查找的那些事:

假设[列1]上有一个单列索引,可以使用这个索引查找下面这些谓词:

1.[列1] = 1.23

2.[列1] > 1.23

3.[列1] BETWEEN 1 AND 100

4.[列1] LIKE 'abc%'

5.[列1] IN (1,3,7,10)

  不能使用这个索引对下列这些谓词进行查找:

1.ABS[列1] = 1

2.[列1] + 10 > 12

3.[列1] LIKE '%abc'

关于非聚集索引的那些事:

  1. 如果只有非聚集索引时,非聚集索引不包含查询列时,则SQL查询优化器选择非聚集索引扫描。
  2. 只有非聚集索引时,非聚集索引不包含过滤条件列时,则选择表扫描。
  3. 非聚集索引具有独立于数据行的结构。 非聚集索引包含非聚集索引键值,并且每个键值项都有指向包含该键值的数据行的指针。
  4. 从非聚集索引中的索引行指向数据行的指针称为行定位器。 行定位器的结构取决于数据页是存储在堆中还是聚集表中。 对于堆,行定位器是指向行的指针。 对于聚集表,行定位器是聚集索引键。
  5. 您可以向非聚集索引的叶级添加非键列(包含列)以跳过现有的索引键限制(900 字节和 16 键列),并执行完整范围内的索引查询。

关于聚集索引的那些事:

1. 如果表上有聚集索引,则扫描称作聚集索引扫描,查找称作聚集索引查找;

2. 聚集索引扫描和表扫描的性能没多大差异;

3.聚集索引根据数据行的键值在表或视图中排序和存储这些数据行。

4.索引定义中包含聚集索引列。

5.每个表只能有一个聚集索引,因为数据行本身只能按一个顺序排序。

6.只有当表包含聚集索引时,表中的数据行才按排序顺序存储。 如果表具有聚集索引,则该表称为聚集表。如果表没有聚集索引,则其数据行存储在一个称为堆的无序结构中。

7.加了聚集索引不一定能提高性能,有些情况下,性能可能不如表扫描;

8.聚集索引就是表本身。表有多少行和多少列,聚集索引就有多少行和和多少列。

9.单表查询中,过滤条件中有聚集索引列,且能用这个索引查找过滤条件中的谓词,则是聚集索引查找,过滤条件中没有聚集索引列则是聚集索引扫描。

(1)没有索引的情况

创建myOrder表

USE [Test]
GO
 
CREATE TABLE [dbo].[myOrder](
[id] [int] NOT NULL,
[customer] [nvarchar](100) NOT NULL
) ON [PRIMARY]
 
GO

myOrder只有两列id,customer,这两列上面都没有索引。

SELECT [id]
FROM [Test].[dbo].[myOrder]
WHERE [customer] = 'ddd'

下面是执行计划:

customer列上面没有索引,SQL Server需要读取myOrder表的每一行来判断customer='ddd',如果结果为true,则返回此行。

查询的示例图如下,customer=ddd 存在三条记录。

注意:

1.扫描及查找是SQL Server用来从表和索引中读取数据的迭代器;

2.扫描用来处理整个表或索引的全部分支;

3.查找是在谓词基础上有效返回索引中一个或多个范围中的行。

(2)有非聚集索引的情况

在id上创建非聚集索引

USE [Test]
GO
 
--删除索引dbo.myOrder.ID_NON_INDEX
DROP INDEX dbo.myOrder.ID_NON_INDEX
 
CREATE NONCLUSTERED INDEX [ID_NON_INDEX] ON [dbo].[myOrder]
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

1.查询条件的列上没有非聚集索引,查询列上没有非聚集索引->表扫描

--id列上有索引,customer列上没有索引,查询条件中用的是customer='ddd'进行过滤。
--由于customer列上没有索引,所以需要进行表扫描来找到符合customer='ddd'的行。
SELECT [id]
FROM [Test].[dbo].[myOrder]
WHERE [customer] = 'ddd' SELECT [customer]
FROM [Test].[dbo].[myOrder]
WHERE [customer] = 'ddd' SELECT [id],[customer]
FROM [Test].[dbo].[myOrder]
WHERE [customer] = 'ddd' SELECT [id]
FROM [Test].[dbo].[myOrder]
WHERE [id] = 2 AND [customer] ='ddd' SELECT [id],[customer]
FROM [Test].[dbo].[myOrder]
WHERE [id] = 2 AND [customer] ='ddd'

2.查询条件的列上有非聚集索引,查询列上没有非聚集索引->表扫描

--id列上有索引,customer列上没有索引,查询条件中用的是id=2进行过滤。
--SELECT查询需要返回customer列,由于customer列上没有索引,且索引[ID_NON_INDEX]不包含customer列,
--即使用非聚集索引扫描找到了符合过滤条件id=2的索引分支,但是只能在该索引分支上面拿到id列的值,因为该索引分支只包含了id列,其他列的值拿不到。
--所以还是需要进行表扫描来找到符合条件的行,然后获取该行的customer列的值。
--这里有个疑问:为什么找到索引分支后,不能继续找到对应的行,然后拿到这行的customer列??
SELECT [customer]
FROM [Test].[dbo].[myOrder]
WHERE [id] = 2 SELECT [id],[customer]
FROM [Test].[dbo].[myOrder]
WHERE [id] = 2

3.查询条件的列上有非聚集索引,查询列上有非聚集索引->索引查找

--id列上有索引,customer列上没有索引,查询条件中用的是id=2进行过滤。
--SELECT查询需要返回id列,使用非聚集索引扫描找到了符合过滤条件id=2的索引分支,在找到的索引分支上拿到id列的值。
SELECT [id]
FROM [Test].[dbo].[myOrder]
WHERE [id] = 2

3)有聚集索引的情况

1.查询条件的列上没有聚集索引->聚集索引扫描

--
--id列上有聚集索引,customer列上没有索引,查询条件中用的是customer='ddd'进行过滤。
--由于customer列上没有索引,所以需要进行扫描来找到符合customer='ddd'的行。
--只要有聚集索引,则扫描就是聚集索引扫描。聚集索引和表扫描的性能基本上一样。
SELECT [id]
FROM [Test].[dbo].[myOrder]
WHERE [customer] = 'ddd' SELECT [customer]
FROM [Test].[dbo].[myOrder]
WHERE [customer] = 'ddd' SELECT [id],[customer]
FROM [Test].[dbo].[myOrder]
WHERE [customer] = 'ddd'

  

2.查询条件的列上有聚集索引->聚集索引查找

--id列上有索引,customer列上没有索引,查询条件中用的是id=2进行过滤。
--用聚集索引查找到了id=2的行,由于表中的行就是按照id列来排序的,所以找到了这一行,
--也就能找到这一行的所有列,所以能够拿到customer列。所以是聚集索引扫描。
SELECT [customer]
FROM [Test].[dbo].[myOrder]
WHERE [id] = 2 SELECT [id]
FROM [Test].[dbo].[myOrder]
WHERE [id] = 2 SELECT [id],[customer]
FROM [Test].[dbo].[myOrder]
WHERE [id] = 2

  

3.查询条件中,有一列有聚集索引,另一列没有聚集索引->聚集索引查找

--id列上有索引,customer列上没有索引,查询条件中用的是[id] = 2,[customer] ='ddd'进行过滤。
--当过滤条件中有一个可以根据聚集索引来查找时,先用聚集索引来找到匹配的行([id] = 2),然后再在过滤出来的行中筛选处符合[customer] ='ddd'的行。
--所以是聚集索引查找。
--疑问:为什么第二步筛选操作在执行计划图中没有体现??这个地方我想到的是拿到id=2的匹配行后,直接舍弃掉不符合条件[customer] ='ddd'的行,这个舍弃动作就没有直接体现出来。
SELECT [id]
FROM [Test].[dbo].[myOrder]
WHERE [id] = 2 AND [customer] ='ddd' SELECT [id],[customer]
FROM [Test].[dbo].[myOrder]
WHERE [id] = 2 AND [customer] ='ddd' SELECT [id],[customer]
FROM [Test].[dbo].[myOrder]
WHERE [customer] ='3333' AND [id] = 2

  

->>【T-SQL】系列文章全文目录(2017-06-26更新)

作  者:
Jackson0714

出  处:http://www.cnblogs.com/jackson0714/

关于作者:专注于微软平台的项目开发。如有问题或建议,请多多赐教!

版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

特此声明:所有评论和私信都会在第一时间回复。也欢迎园子的大大们指正错误,共同进步。或者直接私信

声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是作者坚持原创和持续写作的最大动力!

【T-SQL进阶】03.执行计划之旅-1的更多相关文章

  1. 【SQL进阶】03.执行计划之旅1 - 初探

    听到大牛们说执行计划,总是很惶恐,是对知识的缺乏的惶恐,所以必须得学习执行计划,以减少对这一块知识的惶恐,下面是对执行计划的第一讲-理解执行计划. 本系列[T-SQL]主要是针对T-SQL的总结. S ...

  2. SQL Server 优化-执行计划

    对于SQL Server的优化来说,优化查询可能是很常见的事情.由于数据库的优化,本身也是一个涉及面比较的广的话题, 因此本文只谈优化查询时如何看懂SQL Server查询计划.毕竟我对SQL Ser ...

  3. 了解Sql Server的执行计划

    前一篇总结了Sql Server Profiler,它主要用来监控数据库,并跟踪生成的sql语句.但是只拿到生成的sql语句没有什么用,我们可以利用这些sql语句,然后结合执行计划来分析sql语句的性 ...

  4. 【MS SQL】通过执行计划来分析SQL性能

    原文:[MS SQL]通过执行计划来分析SQL性能 如何知道一句SQL语句的执行效率呢,只知道下面3种: 1.通过SQL语句执行时磁盘的活动量(IO)信息来分析:SET STATISTICS IO O ...

  5. SQL Server实际执行计划COST"欺骗"案例

    有个系统,昨天Support人员发布了相关升级脚本后,今天发现系统中有个功能不能正常使用了,直接报超时了(Timeout expired)的错误.定位到相关相关存储过程后,然后在优化分析的过程中,又遇 ...

  6. 官方文档:11G新特性SQL PLAN BASLINE 执行计划基线

    什么是SQL执行计划管理? SQL计划管理(SQL plan management)是一咱预防机制,记录和评估SQL语句的执行计划.SQL plan management的主要功能是sql plan ...

  7. oracle中查看sql语句的执行计划

    1.在pl/sql中打开cmd命令容器 2.在cmd命令窗口中输入:explain plan for select * from t; 3.查看sql语句的执行计划:select * from tab ...

  8. 程序员眼中的 SQL Server-执行计划教会我如何创建索引?

    先说点废话 以前有 DBA 在身边的时候,从来不曾考虑过数据库性能的问题,但是,当一个应用程序从头到脚都由自己完成,而且数据库面对的是接近百万的数据,看着一个页面加载速度像乌龟一样,自己心里真是有种挫 ...

  9. SQL SERVER 2012 执行计划走嵌套循环导致性能问题的案例

    开发人员遇到一个及其诡异的的SQL性能问题,这段完整SQL语句如下所示: declare @UserId             INT declare @PSANo              VAR ...

随机推荐

  1. NSLog (Log信息的输出)

    概述 NSLog是 cocoa的框架中提供的一个方法 NSLog的定义 NSLog定义在NSObjCRuntime.h中 NSLog与printf的差异 1)NSLog传递进去的格式化字符是NSStr ...

  2. Java AOP (2) runtime weaving 【Java 切面编程 (2) 运行时织入】

    接上一篇 Java AOP (1) compile time weaving [Java 切面编程 (1) 编译期织入] Dynamic proxy   动态代理 Befor talking abou ...

  3. 为程序猿正名,MM们,你们为什么要找一个程序猿男票?【原创】

    前言 免责声明:这篇文章关于什么?六一儿童节马上就要到了,作为一个前端攻城师,自我感觉效率还可以,老早已把任务搞完,页面布局和前端编码高效按时交付,呵呵.趁有时间,写写文章娱乐一下.MM们,请不要拿起 ...

  4. tomcat启动一闪而过问题的解决

    1.今天使用startup.bat启动tomcat报错,现象是一闪而过,在logs文件夹中有没有日志文件, 可以在控制台输入startup.bat,如下:   但是也没有看出什么太有用的错误,然后可以 ...

  5. 由"永恒之蓝"病毒而来的电脑科普知识

    永恒之蓝病毒事件: 继英国医院被攻击,随后在刚刚过去的5月12日晚上20点左右肆虐中国高校的WannaCry勒索事件,全国各地的高校学生纷纷反映,自己的电脑遭到病毒的攻击,文档被加密,壁纸遭到篡改,并 ...

  6. 门面(Facade)模式

    门面模式是对象的结构模式,外部与一个子系统的通信必须通过一个统一的门面对象进行.门面模式提供一个高层次的接口,使得子系统更易于使用. 医院的例子 现代的软件系统都是比较复杂的,设计师处理复杂系统的一个 ...

  7. Sql Server + ADO.NET

    MsSql-http://www.cnblogs.com/zhangwei595806165/archive/2012/02/23/2364746.html 协议:Shared Memory :效率最 ...

  8. 【Python 函数对象 命名空间与作用域 闭包函数 装饰器 迭代器 内置函数】

    一.函数对象 函数(Function)作为程序语言中不可或缺的一部分,但函数作为第一类对象(First-Class Object)却是 Python 函数的一大特性. 那到底什么是第一类对象(Firs ...

  9. tomcat产生大量TIME_WAIT连接

    http://blog.csdn.net/jiangguilong2000/article/details/12523771

  10. Adobe After Effects 2017-14.0安装教程

    Adobe After Effects 2017-14.0安装教程 第一步:首先请将电脑的网络断开,很简单:禁用本地连接或者拔掉网线,这样就可以免除登录Creative Cloud帐号,安装更方便快捷 ...