Ome*_*mer 5 index sql-server execution-plan
我有下表:
CREATE TABLE Test
(
Id int IDENTITY(1,1) NOT NULL,
col1 varchar(37) NULL,
testDate datetime NULL
)
GO
insert Test
select null
go 700000
insert Test
select cast(NEWID() as varchar(37))
go 300000
Run Code Online (Sandbox Code Playgroud)
以及以下索引:
create clustered index CIX on Test(ID)
create nonclustered index IX_RegularIndex on Test(col1)
create nonclustered index IX_RegularDateIndex on Test(testDate)
Run Code Online (Sandbox Code Playgroud)
当我在我的桌子上查询时:
SET STATISTICS IO ON
select * from Test where col1=NEWID()
select * from Test where TestDate=GETDATE()
Run Code Online (Sandbox Code Playgroud)
首先是进行索引扫描,而第二个索引是搜索。我希望他们都必须进行索引查找。为什么先进行索引扫描?
这里的问题是到UNIQUEIDENTIFIER
类型的隐式转换。执行计划中有关于它的警告,它与Data Type Precedence 相关联。
您的表使用了错误的数据类型来存储 GUID。如果col1
正确输入为uniqueidentifier
,您的问题就不会出现。GUID的字符串表示的最大长度为 36(不是 37!)个字符,这比使用uniqueidentifier
(16 个字节)效率低得多。另请注意,NEWID()
返回 a uniqueidentifier
,而不是任何类型的字符串。
我在下面的查询中添加了一些提示以获得相同的执行计划。
如果您分配NEWID()
给一个变量,但您仍然必须声明VARCHAR(37)
变量或只是在 where 子句中强制NEWID()
转换VARCHAR(37)
,则可以避免这种情况。
以下是一些向我们展示其工作原理的查询:
-- Query 1
SELECT * FROM Test WITH(INDEX=[IX_RegularIndex]) WHERE col1=NEWID()
GO
-- Query 2
DECLARE @id UNIQUEIDENTIFIER = NEWID()
SELECT * FROM Test WITH(INDEX=[IX_RegularIndex]) WHERE col1=@id
GO
-- Query 3
DECLARE @id VARCHAR(37) = NEWID()
SELECT * FROM Test WITH(INDEX=[IX_RegularIndex]) WHERE col1=@id
GO
-- Query 4
SELECT * FROM Test WITH(INDEX=[IX_RegularIndex]) WHERE col1=cast(NEWID() as varchar(37))
GO
Run Code Online (Sandbox Code Playgroud)
关于NEWID
函数求值次数的相关问答:
归档时间: |
|
查看次数: |
807 次 |
最近记录: |