SQLSERVER隐式转换剖析.docx
- 文档编号:889245
- 上传时间:2022-10-13
- 格式:DOCX
- 页数:11
- 大小:275.98KB
SQLSERVER隐式转换剖析.docx
《SQLSERVER隐式转换剖析.docx》由会员分享,可在线阅读,更多相关《SQLSERVER隐式转换剖析.docx(11页珍藏版)》请在冰豆网上搜索。
SQLSERVER隐式转换剖析
SQLSERVER中隐式转换的一些细节浅析
其实这是一篇没有技术含量的文章,精通SQL优化的请绕道。
这个缘起于在优化一个SQL过程中,同事问了我一个问题,为什么SQL中存在隐式转换,但是执行计划没有变?
我思索了一下,觉得这个问题也有点意思,说不定有些对隐式转换了解得不深入的同学都有此疑问,那么下面结合上下文场景做一个细节方面的解答。
我们一个系统中使用了ORMLite框架,粗心的开发人员弄出了不少下面这样的SQL语句,都存在隐式转换问题,如下所示,表machine_stop_alarm_msg的结构如下,字段machine_no、status都为VARCHAR(10),但是下面SQL,传入的变量@P0,@P1都是NVARCHAR(4000)类型。
DECLARE @P0nvarchar(4000),@P1nvarchar(4000);
SET@P0='1';
SET@P1='K172';
SELECT[recid],[machine_no]
,[stop_stime]
,[stop_etime]
,[status]
,[memo]
,[createddate]
FROMmachine_stop_alarm_msgt
WHERE1=1
ANDt.status=@P0
ANDt.machine_noin(@P1)
ORDER BYmachine_no,
stop_stime;
machine_stop_alarm_msg表只有一个聚集索引PK_machine_stop_alarm_msg,字段为recid。
当时我优化的时候,就觉得这个SQL语句存在两个问题:
1缺少索引;2存在隐式转换问题。
当时创建了下面索引,并要求开发人员修改SQL,避免隐式转换。
CREATE NONCLUSTERED INDEXix_machine_stop_alarm_msg_n1
ON[dbo].[machine_stop_alarm_msg]([machine_no],[status])
INCLUDE([recid],[stop_stime],[stop_etime],[memo],[createddate])
GO
在测试环境测试时,我们先不增加这个索引,就出现了下面一个场景,两者都是走聚集索引扫描:
1:
执行计划走聚集索引扫描(ClusterIndexScan)
SET STATISTICSIOON;
SET STATISTICS TIME ON;
DECLARE @P0nvarchar(4000),@P1nvarchar(4000);
SET@P0='1';
SET@P1='K172';
SELECT[recid],[machine_no]
,[stop_stime]
,[stop_etime]
,[status]
,[memo]
,[createddate]
FROMmachine__stop_alarm_msgt
WHERE1=1
ANDt.status=@P0
ANDt.machine_noin(@P1)
ORDER BYmachine_no,
stop_stime;
SET STATISTICSIOOFF;
SET STATISTICS TIME OFF;
2:
执行计划走聚集索引扫描(ClusterIndexScan)
SET STATISTICSIOON;
SET STATISTICS TIME ON;
DECLARE @P0VARCHAR(10),@P1VARCHAR(10);
SET@P0='1';
SET@P1='K172';
SELECT[recid],[machine_no]
,[stop_stime]
,[stop_etime]
,[status]
,[memo]
,[createddate]
FROMmachine_stop_alarm_msgt
WHERE1=1
ANDt.status=@P0
ANDt.machine_noin(@P1)
ORDER BYmachine_no,
stop_stime;
SET STATISTICSIOOFF;
SET STATISTICS TIME OFF;
这里两者的执行计划一样,这个应该很好理解,缺少相关索引,而且发生隐式转换的不是索引所在的字段,那么即使存在隐式转换,它的执行计划是一样的。
这里没有太多要解释的。
那么我们接下来看看看增加了索引后,两者的实际执行计划。
现在同事纠结的就是即使发生了隐式转换,为什么执行计划还是走索引查找(IndexSeek)呢?
其实很多人有一个误区,SQLServer当中并不是所有的隐式转换都会导致索引扫描(IndexScan)也就是说隐式转导致索引扫描也是有条件的。
这里不再做展开讲,没有太多意思。
另外,我们再来对比一下两者的执行计划。
上面发生隐式转换的SQL的执行计划,多了一个常量扫描(ConstantScan),常量扫描做的工作是根据用户输入的SQL中的常量生成一个行,MSDN的介绍如下:
"TheConstantScanoperatorintroducesoneormoreconstantrowsinto aquery.AComputeScalaroperatorisoftenusedafteraConstant
ScantoaddcolumnstoarowproducedbytheConstantScanoperator"
常量扫描会引入一个或者多个常量行到一个查询中;通常情况下紧跟常量扫描的是计算标量运算符,计算标量运算符会为常量扫描运算符产生的行添加列。
如果你想知道执行计划里面的Expr1004、Expr1005、Expr1003对应啥,看看执行计划就知道了(其中Expr1003为(62),一开始不明其什么意义,后面咨询了宋大神,才知道62是个flag,意思是等于号)
发生隐式转换的SQL还多了一个NestedLoop(InnerJoin)操作。
另外,即使这两个SQL依然都是索引查找(IndexSeek),但是两种的IO开销还是有所区别的。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- SQLSERVER 转换 剖析
![提示](https://static.bdocx.com/images/bang_tan.gif)