[转帖]SQL SERVER中隐式转换的一些细节浅析
https://www.cnblogs.com/kerrycode/p/5853257.html
其实这是一篇没有技术含量的文章,精通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中隐式转换的一些细节浅析
其实这是一篇没有技术含量的文章,精通SQL优化的请绕道.这个缘起于在优化一个SQL过程中,同事问了我一个问题,为什么SQL中存在隐式转换,但是执行计划没有变? 我思索了一下,觉得这个问题也有点意思,说 ...
- SQL Server 隐式转换引发的躺枪死锁-程序员需知
在SQL Server的应用开发过程(尤其是二次开发)中可能由于开发人员对表的结构不够了解,造成开发过程中使用了不合理的方式造成数据库引擎未按预定执行,以致影响业务.这是非常值得注意的.这次为大家介绍 ...
- SQL Server 隐式转换引发的死锁
在SQL Server的应用开发过程(尤其是二次开发)中可能由于开发人员对表的结构不够了解,造成开发过程中使用了不合理的方式造成数据库引擎未按预定执行,以致影响业务.这是非常值得注意的.这次为大家介绍 ...
- SQL Server中行列转换 Pivot UnPivot
SQL Server中行列转换 Pivot UnPivot PIVOT用于将列值旋转为列名(即行转列),在SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT的一般语法是:PI ...
- SQL Server全时区转换
SQL Server全时区转换 假如你的应用程序是跨国(例如跨国银行交易)使用的话,那么数据库的一些国际化特性支持可以说是非常重要 其中最常见的就是各国时区上的差异,由于SQL Server getd ...
- piap.excel 微软 时间戳转换mssql sql server文件时间戳转换unix 导入mysql
piap.excel 微软 时间戳转换mssql sql server文件时间戳转换unix 导入mysql 需要不个mssql的sql文件导入mysql.他们的时间戳格式不同..ms用的是自定义的时 ...
- Scala 深入浅出实战经典 第65讲:Scala中隐式转换内幕揭秘、最佳实践及其在Spark中的应用源码解析
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
- sql server动态行列转换
原文链接:https://www.cnblogs.com/gaizai/p/3753296.html sql server动态行列转换 一.本文所涉及的内容(Contents) 本文所涉及的内容(Co ...
- SQL Server中datetimeset转换datetime类型问题浅析
在SQL Server中,数据类型datetimeoffset转换为datetime类型或datetime2类型时需要特别注意,有可能一不小心你可能会碰到下面这种情况.下面我们构造一个简单案例,模拟一 ...
- SQL Server 进制转换函数
一.背景 前段时间群里的朋友问了一个问题:“在查询时增加一个递增序列,如:0x00000001,即每一个都是36进位(0—9,A--Z),0x0000000Z后面将是0x00000010,生成一个像下 ...
随机推荐
- Docker本地部署Firefox火狐浏览器并远程访问
Docker本地部署Firefox火狐浏览器并远程访问 Firefox是一款免费开源的网页浏览器,由Mozilla基金会开发和维护.它是第一个成功挑战微软Internet Explorer浏览器垄断地 ...
- 文心一言 VS 讯飞星火 VS chatgpt (23)-- 算法导论4.2 5题
五.V.Pan 发现一种方法,可以用 132 464 次乘法操作完成 68 x 68 的矩阵相乘,发现另一种方法,可以用 143 640 次乘法操作完成 70 x 70 的矩阵相乘,还发现一种方法,可 ...
- vue全屏
<template> <div> <img src="../assets/fangda.png" @click="toggleFullscr ...
- SQLite3使用笔记(1)——查询
目录 1. 概述 2. 详论 2.1. 打开/关闭数据库 2.2. 数据查询 3. 参考 1. 概述 SQLite是一个嵌入式SQL数据库引擎.与大多数其他 SQL 数据库不同,SQLite 没有单独 ...
- LiteOS:盘点那些重要的数据结构
摘要:本文会给读者介绍下LiteOS源码中常用的几个数据结构,包括: 双向循环链表LOS_DL_LIST,优先级队列Priority Queue,排序链表SortLinkList等. 在学习Huawe ...
- 一文带你了解GaussDB(DWS) 的Roach逻辑备份实现原理
摘要:Roach工具是GaussDB(DWS)推出的一款主力的备份恢复工具,包含物理与逻辑备份两种主要能力,本文着重于讲解Roach逻辑备份的实现原理. 一.简介 在大数据时代,数据的完整和可靠性成为 ...
- MindSpore:不用摘口罩也知道你是谁
[本期推荐专题]从三大主流前端技术出发,看看它们各自特性,以及如何从业务特性出发,选择合适的框架. 摘要:我们基于MindSpore设计了一种人脸识别算法,以解决口罩遮挡场景下的人脸识别问题.该算法的 ...
- Redisson:这么强大的实现分布式锁框架,你还没有?
摘要:Redisson框架十分强大,基于Redisson框架可以实现几乎你能想到的所有类型的分布式锁. 本文分享自华为云社区<[高并发]你知道吗?大家都在使用Redisson实现分布式锁了!!& ...
- 火山引擎DataTester:如何使用A/B测试优化全域营销效果
当前,营销技术步入了全渠道.全周期的全域时代,随着广泛的数据积累,数据科学技术在营销领域发挥着越来越重要的作用,从消费者人群洞察到智能化信息广告投放,营销的提效让企业得以在转化的每个环节提升影响力 ...
- Java 图片、文件 Base64 互转
Java 图片.文件 Base64 互转 package com.thoth.his.base.util; import java.io.FileInputStream; import java.io ...