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下一些归类。
NVARCHARto没有这样的例外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 次 |
| 最近记录: |