SSMS执行计划对比功能

简介: 在很长一段时间,我们都被一个问题困扰:如何高效的对比SQL Server执行计划的差异?这篇文章就是要来看看SSMS工具是如何解决执行计划对比功能的。

问题引入

“鸟儿,我一直有个疑问,在很多时候,被客户问道,为什么非常相似的两个查询语句执行计划天壤之别?”。老鸟已经开始在请教菜鸟问题了。
“这种时候,大部分情况是由于查询语句走的执行计划不一样导致的。”菜鸟卖起了关子。
“那如何高效的对比执行计划的差异呢?”老鸟穷追猛问。
“这个嘛,我自有妙招,且听我细细道来”。

问题分析

SSMS图形化展示SQL Server查询语句执行计划已经是非常牛X的功能了,如果SSMS再完善加入执行计划对比功能的话,一定会解决老鸟的痛点,大放异彩。没想到地球人真的没能阻止SSMS吊炸天的步伐。SSMS 2016中,已经具备了执行计划对比功能。
01.png

使用方法

以下是SSMS执行计划对比功能的详细介绍。

创建测试环境

创建测试环境包括创建:测试数据库、测试表和插入100万条测试数据。

-- Create testing database
IF DB_ID('ExecPlanCompare') IS NULL
    CREATE DATABASE ExecPlanCompare;
GO

USE ExecPlanCompare
GO
SET NOCOUNT ON

-- create demo table SalesOrder
IF OBJECT_ID('dbo.SalesOrder', 'U') IS NOT NULL
BEGIN
    DROP TABLE dbo.SalesOrder
END
GO
CREATE TABLE dbo.SalesOrder
(
    OrderID BIGINT IDENTITY(1,1) NOT NULL
    ,AutoID INT NOT NULL
    ,UserID INT NOT NULL
    ,OrderQty INT NOT NULL
    ,Price DECIMAL(8,2) NOT NULL
    ,OrderDate DATETIME NOT NULL,
    CONSTRAINT PK_SalesOrder PRIMARY KEY NONCLUSTERED (OrderID)
);
GO

-- Create Cluster Column Store Index
CREATE CLUSTERED COLUMNSTORE INDEX CCSI_SalesOrder ON dbo.SalesOrder;
;
GO

-- init 1000000 records
;WITH a 
AS (
    SELECT * 
    FROM (VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) AS a(a)
), RoundData
AS(
SELECT TOP(1000000)
    AutoIDRound = abs(checksum(newid()))
    ,Price = a.a * b.a * 500
FROM a, a AS b, a AS c, a AS d, a AS e, a AS f, a AS g, a AS h
)
INSERT INTO dbo.SalesOrder(AutoID, UserID, OrderQty, Price, OrderDate)
SELECT 
    AutoID = cast(ROUND((14 * (AutoIDRound*1./cast(replace(AutoIDRound, AutoIDRound, '1' + replicate('0', len(AutoIDRound))) as bigint)) + 1), 0) as int)
    ,UserID = cast(ROUND((500 * (AutoIDRound*1./cast(replace(AutoIDRound, AutoIDRound, '1' + replicate('0', len(AutoIDRound))) as bigint)) + 10000), 0) as int)
    ,OrderQty = cast(ROUND((2 * (AutoIDRound*1./cast(replace(AutoIDRound, AutoIDRound, '1' + replicate('0', len(AutoIDRound))) as bigint)) + 1), 0) as int)
    ,Price = cast(Price AS DECIMAL(8,2))
    ,OrderDate = dateadd(day, -cast(ROUND((1099 * (AutoIDRound*1./cast(replace(AutoIDRound, AutoIDRound, '1' + replicate('0', len(AutoIDRound))) as bigint)) + 1), 0) as int) ,'2017-01-10')
FROM RoundData;

参照组执行计划

最好生成参照组实际执行计划,而不是预估的执行计划。

-- get the execution plan for using PK
SELECT 
    ord.AutoID
    ,TotalAmount = ISNULL(SUM(ord.Price * ord.OrderQty), 0.00)
    ,TotalQty = ISNULL(SUM(ord.OrderQty), 0.00)
FROM dbo.SalesOrder AS ord WITH(INDEX = PK_SalesOrder)
GROUP BY ord.AutoID

生成实际执行的方法是:
 打开采集实际执行计划的开关
 执行查询语句获取实际执行计划
 在Execution Plan窗口右键点击,然后选择:Save Execution Plan As ...,选择要保存执行计划的目录和名字。
整个过程如下图展示:
02.png

对比组执行计划

同样打开实际执行计划开关,执行以下对比组SQL查询语句,获取实际执行计划。

-- get the execution plan for using CCSI
SELECT 
    ord.AutoID
    ,TotalAmount = ISNULL(SUM(ord.Price * ord.OrderQty), 0.00)
    ,TotalQty = ISNULL(SUM(ord.OrderQty), 0.00)
FROM dbo.SalesOrder AS ord WITH(INDEX = CCSI_SalesOrder)
GROUP BY ord.AutoID

在Execution Plan窗口任意位置,右键点击,选择 Compare Showplan。如下图展示:
03.png
浏览到上一小节“参照组执行计划”保存的文件。
04.png

执行计划上下对比

接下来是见证奇迹的时刻,看看两个查询语句的执行计划对比效果图:
05.png
整个窗口由三部分组成:
 执行计划对比窗口:两个执行计划的详细图形展示。
 执行计划对比选项:对比选项的设置和执行计划语句对比展示。
 属性窗口:详细的执行计划指标对比展示。比如:这里我们就可以很容易对比出使用聚集列存储索引查询CPU和执行时间分别是7和9;而使用主键查询CPU和执行时间是26114和16176。明显前者性能高太多了,如果没有执行计划的对比功能,我们就很难这么形象的对比出他们之间的执行计划差异。

执行计划左右对比

如果你不喜欢上下位置,我们一二三四,换个姿势,左右对比好了。方法非常简单,右键点击执行计划对比窗口任何位置,然后选择”Toggle Splitter Orientation”。
06.png
位置交换完毕,细心的你一定发现属性窗口也有了细微的变化。
07.png

动作对比

SSMS对比功能做到这里,已经灰常牛逼了,对不对?我们可以使用SSMS的对比功能对比出两个查询语句的执行计划详细差异。还有更牛X的功能呢,我们可以对比每个非常细小的动作差异,是不是更牛逼,等不及要看看了?简单,只需要在执行计划对比窗口中左右(或者上下)子窗口选中要对比的动作即可。比如:左边窗口我们选中Columnstore Index Scan (Clustered),右边窗口我们选择Index Scan (Nonclustered)。这时,属性窗口中会展示相应被选择动作的详细对比情况,一目了然。
08.png

写在最后

由于之前很长一段时间,自己感动身受,在对比两个查询语句执行计划的差异时,非常痛苦与不便,需要耗费非常大的精力和时间。SSMS具备执行计划对比功能以后,解决了这个痛点,妈妈再也不用担心执行计划对比烧脑的事情了。

目录
相关文章
|
6月前
|
SQL Linux 数据库
如何安装数据库sql
安装SQL Server数据库的步骤通常包括以下几个阶段。请注意,具体步骤可能会因SQL Server版本和操作系统环境的不同而有所差异。以下是一个一般性的安装指南: 1. **准备工作**:
|
SQL 存储 Oracle
一次搞定各种数据库SQL执行计划
执行计划(execution plan,也叫查询计划或者解释计划)是数据库执行 SQL 语句的具体步骤,例如通过索引还是全表扫描访问表中的数据,连接查询的实现方式和连接的顺序等。如果 SQL 语句性能不够理想,我们首先应该查看它的执行计划。
一次搞定各种数据库SQL执行计划
|
SQL 关系型数据库 MySQL
十九、使用explain分析你SQL执行计划
十九、使用explain分析你SQL执行计划
96 0
|
SQL 存储 Oracle
Oracle数据库 | SQL语句执行计划、语句跟踪与优化实例
Oracle数据库 | SQL语句执行计划、语句跟踪与优化实例
341 0
|
SQL 关系型数据库 MySQL
二十二、查询分析器 EXPLAIN
二十二、查询分析器 EXPLAIN
174 0
二十二、查询分析器 EXPLAIN
|
SQL 数据库连接 数据库
SQL Server数据库连接工具SSMS18.2的安装与配置
SQL Server数据库连接工具SSMS18.2的安装与配置
157 0
SQL Server数据库连接工具SSMS18.2的安装与配置
|
数据库连接
ACCESS数据库连接查询语句
  基于视频讲解中的实现语句,包括:LEFT JOIN(左连接)、RIGHT JOIN(右连接)、INNER JOIN(内连接)和笛卡尔积加条件,语句的写法格式如下:   LEFT JOIN(左连接)   SELECT a.*, b.英语分数 AS 英语期中分数   FROM 入学成绩 AS a   LEFT JOIN 期中成绩 AS b   ON a.学号=b.学号;RIGHT JOIN(右连接)
168 0
|
存储 SQL 缓存
数据库必知词汇:MySQL查询执行计划(Explain)
MySQL的EXPLAIN命令可以查看SELECT语句的执行的计划,是 MySQL 查询优化的必备工具。通过执行计划可以了解查询方式、索引使用情况、需要扫描的数据量以及是否需要临时表或排序操作等信息。我们需要分析执行计划对查询进行有的放矢的优化。
626 0