也谈SQL Server 2008 处理隐式数据类型转换在执行计划中的增强 (续)

原创 2015年07月03日 16:58:57

在上一篇文章也谈SQL Server 2008 处理隐式数据类型转换在执行计划中的增强 中,我提到了隐式数据类型转换增加对于数据分布很不平均的表,评估的数据行数与实际值有很大出入的问题,进一步测试之后,我发现这种评估不准确性应该确实与猜测的一样,它使用了变量的评估方式。通过如下测试验证,首先建立数据分布不平均的测试表。

USE tempdb
GO
CREATE TABLE _t(
    c varchar(50)
);
CREATE INDEX IX_c ON _t( c );
GO

-- 加入 10000 条数据
INSERT _t
SELECT (9999 + id) FROM(
    SELECT TOP 10000 id = ROW_NUMBER() OVER( ORDER BY GETDATE() )
    FROM sys.all_columns a, sys.all_columns
)ID

-- 将 100 - 10000 的数据变成相同值
UPDATE _t SET c = '' WHERE c >= '10100'

然后通过 varhcar和nvarchar值分别测试满足条件1条和满足条件8900条的执行计划预估行数。

ALTER INDEX IX_c ON _t REBUILD;
GO
SET SHOWPLAN_ALL ON
GO
SELECT * FROM _t WHERE c = '10005';     -- 实际1条
GO
SET SHOWPLAN_ALL OFF;
GO

ALTER INDEX IX_c ON _t REBUILD;
GO
SET SHOWPLAN_ALL ON
GO
SELECT * FROM _t WHERE c = N'10005';     -- 实际1条
GO
SET SHOWPLAN_ALL OFF;
GO

ALTER INDEX IX_c ON _t REBUILD;
GO
SET SHOWPLAN_ALL ON
GO
SELECT * FROM _t WHERE c = '';          -- 实际9900条
GO
SET SHOWPLAN_ALL OFF;
GO

ALTER INDEX IX_c ON _t REBUILD;
GO
SET SHOWPLAN_ALL ON
GO
SELECT * FROM _t WHERE c = N'';         -- 实际9900条
GO
SET SHOWPLAN_ALL OFF;
GO

得到的查询计划预估行数如下图所示
这里写图片描述
从图中显示的预估数据行数可以看到,对于varchar值(不需要隐匿的数据类型转换),其预估的结果是准确的。但对于nvarchar值,不管指定的值是只有一条数据,还是有8900条数据匹配,其预估的结果都是99.0099,这说明预估并没有考虑我们指定的值。
进一步用变量测试

ALTER INDEX IX_c ON _t REBUILD;
GO
SET SHOWPLAN_ALL ON
GO
DECLARE @v varchar;SELECT * FROM _t WHERE c = @v; -- varchar
GO
SET SHOWPLAN_ALL OFF;
GO

ALTER INDEX IX_c ON _t REBUILD;
GO
SET SHOWPLAN_ALL ON
GO
DECLARE @nv nvarchar;SELECT * FROM _t WHERE c = @nv; -- nvarchar
GO
SET SHOWPLAN_ALL OFF;
GO

结果如下图所示:
这里写图片描述

不管是varchar,还是nvarchar的变量,预估的行数都是99.0099,这个值与使用nvarchar常量值的结果一样,看来SQL Server查询优化器应该确实把 GetRangeThroughConvert 的结果看成变量了,这个应该是设计上考虑不太周全的地方了,毕竟指定固定常量值的时候,GetRangeThroughConvert的结果应该也是确定值才对。(这个问题在 SQL Server 2014中看起来是调整过来了,在2014中测试没有发现这样的现象)。

JS各种类型问题与隐式类型转换

由于JS中的数据类型是松散类型,并且其在进行操作符运算时并不会像C++和Java一样先检测数据类型,而是隐式的进行数据类型转换,返回值有时并不如我们想象的那样。尤其是对于像&&操作符涉及到短路操作,并...
  • Debbie1993
  • Debbie1993
  • 2016年03月24日 16:30
  • 1414

Oracle DB 隐式和显示数据类型转换

转换函数 除了Oracle  数据类型,还可以使用美国国家标准协会(ANSI) 、DB2 和SQL/DS  数据类型定义Oracle DB 中表的列。但是,Oracle Server  会在...
  • rlhua
  • rlhua
  • 2013年10月17日 09:22
  • 8161

Oracle的隐式转换

都说Oracle存在NUMBER和VARCHAR2类型的隐式转换,严格意义上需要避免,但为何需要避免,从下面的实验进行验证。 1. 创建测试表和索引 create table tn (id numb...
  • bisal
  • bisal
  • 2015年03月06日 19:06
  • 3348

Oracle查询隐式类型转换不走索引

1. 框架 mybatis,oracle 2. 问题 昨天DBA发来邮件说有一个SQL引起CPU高负载。查看了一下SQL,根据时间条件查询,时间是有索引的,但是CPU会突然飙高。 SELECT *...
  • xcylive520
  • xcylive520
  • 2016年02月20日 18:43
  • 597

oracle 隐式转换

原文地址:http://blog.itpub.net/29324876/viewspace-1096741/ 1     Oracle 隐式转换 Oracle中对不同类型的处理具有显式类型...
  • u013419080
  • u013419080
  • 2016年10月13日 11:03
  • 518

java中显示类型转换和隐式类型转换

在定义变量时,有许多要注意的问题,一不小心就会出现损失精度或者不兼容类型等问题。 例如:     1.定义长整型数据时,必须加后缀l或L               long l =123456...
  • liu1pan2min3
  • liu1pan2min3
  • 2015年09月06日 22:11
  • 2920

c++避免隐式转换

c++避免隐式转换C++有一个很方便的功能—隐式转换,比如有一个函数void func(double f);调用它的时候func(5); func(5.0);都是有效的。但有时候,这个功能就很麻烦了。...
  • LaineGates
  • LaineGates
  • 2016年01月28日 11:00
  • 1444

Java的强制类型转换与隐式类型转换

一.隐式类型转换1.Java中的8大基本数据类型java基本数据类型就8种,除了这些都是引用型的了。java四类八种基本数据类型: 第一类:整型 byte short int long 第二类:浮...
  • u011983531
  • u011983531
  • 2015年10月18日 10:58
  • 1805

也议MySQL中隐式转换

1. 环境说明 RHEL 6.4 x86_64 + MySQL 5.6.19 测试表: MySQL [test]> show create table emp\G ******************...
  • HW_LiBo
  • HW_LiBo
  • 2014年09月13日 16:25
  • 4614

深入理解Scala中的隐式转换系统

博客核心内容: 1、Scala中的两种隐式转换机制以及隐式视图的定义方式 2、Scala中的隐式绑定可能所处的位置以及如何更好的使用隐式转换 3、Scala中的隐式转换相关操作规则 4、Sca...
  • a2011480169
  • a2011480169
  • 2016年11月02日 11:24
  • 5405
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:也谈SQL Server 2008 处理隐式数据类型转换在执行计划中的增强 (续)
举报原因:
原因补充:

(最多只允许输入30个字)