2016-12-02 29 views
4

我有如下表:Where子句索引扫描 - 索引查找

CREATE TABLE Test 
(
    Id int IDENTITY(1,1) NOT NULL, 
    col1 varchar(37) NULL, 
    testDate datetime NULL 
) 

insert Test 

select null 
go 700000 

select cast(NEWID() as varchar(37)) 
go 300000 

及以下指标:

create clustered index CIX on Test(ID) 
create nonclustered index IX_RegularIndex on Test(col1) 
create nonclustered index IX_RegularDateIndex on Test(testDate) 

当我在我的表中查询:

SET STATISTICS IO ON 
select * from Test where col1=NEWID() 
select * from Test where TestDate=GETDATE() 

首先是使索引扫描,而第二个索引查找。我期望他们都必须进行索引查找。为什么第一次进行索引扫描?

enter image description here

回答

5

有监守的NEWID()函数生成的隐式转换返回的值是uniqueidentifier数据类型的,并且比申报的列中VARCHAR数据类型不同。

只要将鼠标悬停在计划的SELECT部分上,那里有“警告”标志。

由于比较数据类型之间存在不匹配的情况,因此优化程序无法查看统计信息并估计表中存在该数值的行数。

因为隐性转换的同时,优化从而判定其是更好的去把所有的行(因此SCAN),然后通过FILTER操作,其中它的Col1价值的转换通过他们到uniqueidentifier数据类型,然后删除不符合筛选条件的其他行。

与之相对GETDATE()它返回一个datetime值,这是相同的数据类型作为testDate列的,所以不需要数据类型转换和因为它们的值进行比较。

+1

有关将导致索引扫描的隐式转换的更多信息可以在此处找到:https://www.sqlskills.com/blogs/jonathan/implicit-conversions-that-c​​ause-index-scans/ –

+0

是的,有如此多的关于隐式转换的信息,我也会尝试添加一些。但大多数时候这是罪魁祸首之一。 –

+0

@OmerK对不起,我误读了,我的意思是'VARCHAR'。 –

相关问题