SQL SERVER中隐式转换的一些细节浅析
其实这是一篇没有技术含量的文章,精通SQL优化的请绕道。这个缘起于在优化一个SQL过程中,同事问了我一个问题,为什么SQL中存在隐式转换,但是执行计划没有变? 我思索了一下,觉得这个问题也有点意思,说不定有些对隐式转换了解得不深入的同学都有此疑问,那么下面结合上下文场景做一个细节方面的解答。
我们一个系统中使用了ORMLite框架,粗心的开发人员弄出了不少下面这样的SQL语句,都存在隐式转换问题,如下所示,表machine_stop_alarm_msg 的结构如下,字段machine_no、status都为VARCHAR(10),但是下面SQL,传入的变量@P0,@P1都是NVARCHAR(4000)类型。
DECLARE @P0 nvarchar(4000),@P1 nvarchar(4000);
SET @P0='1';
SET @P1='K172';
SELECT [recid],[machine_no]
,[stop_stime]
,[stop_etime]
,[status]
,[memo]
,[createddate]
FROM machine_stop_alarm_msg t
WHERE 1=1
AND t.status=@P0
AND t.machine_no in(@P1 )
ORDER BY machine_no,
stop_stime ;
machine_stop_alarm_msg 表只有一个聚集索引PK_machine_stop_alarm_msg,字段为recid。
当时我优化的时候,就觉得这个SQL语句存在两个问题:1 缺少索引; 2 存在隐式转换问题。当时创建了下面索引,并要求开发人员修改SQL,避免隐式转换。
CREATE NONCLUSTERED INDEX ix_machine_stop_alarm_msg_n1
ON [dbo].[machine_stop_alarm_msg] ([machine_no],[status])
INCLUDE ([recid],[stop_stime],[stop_etime],[memo],[createddate])
GO
在测试环境测试时,我们先不增加这个索引,就出现了下面一个场景,两者都是走聚集索引扫描:
1: 执行计划走聚集索引扫描(Cluster Index Scan)
SET STATISTICS IO ON;
SET STATISTICS TIME ON;
DECLARE @P0 nvarchar(4000),@P1 nvarchar(4000);
SET @P0='1';
SET @P1='K172';
SELECT [recid],[machine_no]
,[stop_stime]
,[stop_etime]
,[status]
,[memo]
,[createddate]
FROM machine_stop_alarm_msg t
WHERE 1=1
AND t.status=@P0
AND t.machine_no in(@P1 )
ORDER BY machine_no,
stop_stime ;
SET STATISTICS IO OFF;
SET STATISTICS TIME OFF;
2: 执行计划走聚集索引扫描(Cluster Index Scan)
SET STATISTICS IO ON;
SET STATISTICS TIME ON;
DECLARE @P0 VARCHAR(10),@P1 VARCHAR(10);
SET @P0='1';
SET @P1='K172';
SELECT [recid],[machine_no]
,[stop_stime]
,[stop_etime]
,[status]
,[memo]
,[createddate]
FROM machine_stop_alarm_msg t
WHERE 1=1
AND t.status=@P0
AND t.machine_no in(@P1 )
ORDER BY machine_no,
stop_stime ;
SET STATISTICS IO OFF;
SET STATISTICS TIME OFF;
这里两者的执行计划一样,这个应该很好理解,缺少相关索引,而且发生隐式转换的不是索引所在的字段,那么即使存在隐式转换,它的执行计划是一样的。 这里没有太多要解释的。
那么我们接下来看看看增加了索引后,两者的实际执行计划。
现在同事纠结的就是即使发生了隐式转换,为什么执行计划还是走索引查找(Index Seek)呢? 其实很多人有一个误区,SQL Server当中并不是所有的隐式转换都会导致索引扫描(Index Scan),关于这个请见我这篇博客SQL SERVER中什么情况会导致索引查找变成索引扫描 。也就是说隐式转导致索引扫描也是有条件的。这里不再做展开讲,没有太多意思。另外,我们再来对比一下两者的执行计划。
上面发生隐式转换的SQL的执行计划,多了一个常量扫描(Constant Scan),常量扫描做的工作是根据用户输入的SQL中的常量生成一个行 ,MSDN的介绍如下:
"The Constant Scan operator introduces one or more constant rows into a query. A Compute Scalar operator is often used after a Constant
Scan to add columns to a row produced by the Constant Scan operator"
常量扫描会引入一个或者多个常量行到一个查询中;通常情况下紧跟常量扫描的是计算标量运算符,计算标量运算符会为常量扫描运算符产生的行添加列。
如果你想知道执行计划里面的Expr1004、 Expr1005、Expr1003对应啥,看看执行计划就知道了(其中Expr1003为(62),一开始不明其什么意义,后面咨询了宋大神,才知道62是个flag,意思是等于号)
发生隐式转换的SQL还多了一个Nested Loop(Inner Join)操作。另外,即使这两个SQL依然都是索引查找(Index Seek),但是两种的IO开销还是有所区别的。
SQL SERVER中隐式转换的一些细节浅析相关推荐
- SQL Server中行列转换 Pivot UnPivot (转载)
SQL Server中行列转换 Pivot UnPivot PIVOT用于将列值旋转为列名(即行转列),在SQL Server 2000可以用聚合函数配合CASE语句实现PIVOT的一般语法是:PIV ...
- html中隐式转换成数字,详解JS中的隐式类型转换
JS中隐式类型转换 JS中的数据类型 JS中的数据类型分为两大类: 1.基本数据类型: 1.String 字符串 表示一段文本,例如:人的姓名.地址等 2.Number 数值 3.Boolean 布尔 ...
- SQL Server全时区转换
SQL Server全时区转换 假如你的应用程序是跨国(例如跨国银行交易)使用的话,那么数据库的一些国际化特性支持可以说是非常重要 其中最常见的就是各国时区上的差异,由于SQL Server getd ...
- SQL Server 数据库之转换函数
转换函数 1. 概述 2. Cast 函数 3. Convert 函数 1. 概述 SQL Server 数据库中,不同类型的数据进行运算时:游优先级低的类型会自动转换为优先级搞得数据类型,即隐式转换 ...
- sqlserver2000换成mysql_将Microsoft SQL Server 2000数据库转换成MySQL数据库
1. 下载并安装MyODBC.(如果是XP请下载5.3的旧版本,8.x的新版本运行有问题) 2. 创建一个空的MySQL数据库. 3. 在Windows >> 控制面板 >> ...
- 也议MySQL中隐式转换
1. 环境说明 blog地址:http://blog.csdn.NET/hw_libo/article/details/39252427 RHEL 6.4 x86_64 + MySQL 5.6.19 ...
- SQL server日期格式转换
日期格式转换 字符串转日期时间: convert(datetime,'2017-12-12 00:00:01', 20) 日期时间转字符串: Select CONVERT(varchar(100), ...
- Sql Server 日期格式转换
轉自:http://www.cnblogs.com/JoeDZ/archive/2008/08/19/1270917.html SQL Server中文版的默认的日期字段datetime格式是yyyy ...
- 【转】SQL Server中行列转换 Pivot UnPivot
PIVOT用于将列值旋转为列名(即行转列),在SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT的一般语法是:PIVOT(聚合函数(列) FOR 列 in (-) )AS P ...
- SQL Server日期格式转换大全
Sql Server 中一个非常强大的日期格式化函数 Select CONVERT(varchar(100), GETDATE(), 0): 05 16 2006 10:57AM Select CON ...
最新文章
- 一文详尽2019全年AI技术突破
- python自学路线-零基础Python学习路线,小白的进阶之路!
- 用linux遇到的一个死循环
- Mysql:好好的索引,为什么要下推?
- WSDL SOAP 绑定
- [Java基础]复制文件的异常处理try...catch...finally的做法
- wso2 esb_使用WSO2 ESB进行邮件内容过滤
- ad中那个快捷键是重复上一部_Excel中的F4快捷键用的好,告别加班没烦恼!
- hdu4000 amp;amp; hrbust1625
- C#中你可能不知道的8件事(zz)
- cad安装日志文件发生错误_Autocad 2012 安装失败,某些产品无法安装。有日志文件,拜托求大神帮忙看看如何解决?...
- 如何设置内网端口映射外网
- BZOJ3709 Bohater 贪心
- JavaFX Scene Builder的使用
- 计算机网络基础学习笔记
- PMP(第六版)中的沟通方法
- 【附源码】计算机毕业设计JAVA医院病历管理系统
- D3.js v5.0 旭日图
- 42 《养育的选择》-豆瓣评分8.8
- H3C配置三层交换机配置实例
热门文章
- Atitit 多继承实现解决方案 java c#
- Atititjs javascript异常处理机制与java异常的转换.js exception process
- paip.刮刮卡砸金蛋抽奖概率算法跟核心流程.
- paip.提升用户体验--radio图片选择器 easyui 实现..
- paip.消除 Java 的冗长try/catch/finally
- paip.提升用户体验----gcc c++ 编译速度提升by预编译头技术 .doc
- paip.设置鼠标灵敏度API
- 王川: 重要的东西, 往往是看不见的
- (转)别只盯着比特币!“野蛮生长”的ICO江湖:2年30倍只是寻常
- 新兴IT企业特斯拉(四)——Model 3