jer*_*ech 5 performance sql-server execution-plan view type-conversion query-performance
假设我有一张桌子:
-- just for test purposes
CREATE TABLE SomeTable (
ID INT IDENTITY(1,1) NOT NULL CONSTRAINT PK__SomeTable__ID PRIMARY KEY CLUSTERED
,SomeColumn1 NVARCHAR(50) NULL
,SomeColumn2 DATETIME NULL
);
-- populate table with some rows
INSERT INTO SomeTable DEFAULT VALUES;
GO 1000
Run Code Online (Sandbox Code Playgroud)
因为第三方应用程序有一个视图将表的 ID 列从INT
到NVARCHAR
(假设它是必须的):
CREATE VIEW ThirdPartyView AS
SELECT
ID = CAST(ID as NVARCHAR(10))
,C1 = SomeColumn1
,C2 = SomeColumn2
FROM SomeTable;
Run Code Online (Sandbox Code Playgroud)
然后当我通过 ID 访问一行时,我得到一个 INDEX SCAN:
SELECT *
FROM ThirdPartyView
WHERE ID = N'1'
Run Code Online (Sandbox Code Playgroud)
我明白为什么。
我该怎么做才能在查询之外获得 INDEX SEEK?
社论/情况:
NVARCHAR
. 不幸的是,我必须满足这个条件。或者我被告知要见他们。如果不是,他们的应用程序可能会失败。问题是您通过视图进行的查询与执行相同
SELECT *
FROM SomeTable
WHERE CAST(SomeTable.ID as NVARCHAR(10)) = N'1'
Run Code Online (Sandbox Code Playgroud)
CAST
谓词中的几乎任何一列都会使该谓词不可判断。我所知道的唯一的例外是一个CAST
的datetime
列date
和VARCHAR
至NVARCHAR
下一些归类。
NVARCHAR
to没有这样的例外INT
。
你可能希望它会做类似的事情
WHERE SomeTable.ID = TRY_CAST('Your search string' as int)
Run Code Online (Sandbox Code Playgroud)
但事情并没有那么简单。如果您的搜索字符串是'1'
两个将返回相同的结果,但对于搜索字符串'¹'
(上标 1),转换int
失败但字符串比较在某些排序规则下比较相等。相反,对于搜索字符串' 1'
(带有前导空格),转换int
和比较将丢弃前导空格并比较相等,但字符串比较将比较不相等(与0
转换为时转换为的空字符串类似int
)
可能的解决方案
通常,您可以在引用计算列的基表上创建索引视图或新索引,但与CAST
从视图中删除以便可以查找现有索引相比,两者似乎都不太理想。
计算列
您可以SomeTable
使用定义创建一个计算列CAST(ID as NVARCHAR(10))
,然后对其进行索引。
ALTER TABLE SomeTable ADD strID AS CAST(ID as NVARCHAR(10));
CREATE INDEX IX ON SomeTable (strID ) INCLUDE (ID, SomeColumn1, SomeColumn2);
SELECT *
FROM ThirdPartyView
WHERE ID = N'1';
Run Code Online (Sandbox Code Playgroud)
索引视图
鉴于问题中的限制,计算列的想法似乎被排除在外。另一种方法是创建索引视图,但您可能需要更改查询文本才能使其正常工作。
NOEXPAND
需要提示来获取要匹配的索引视图。 归档时间: |
|
查看次数: |
257 次 |
最近记录: |