Dav*_*vre 14 sql-server index-tuning computed-column
我想根据两列是否相等进行快速查找。我尝试使用带有索引的计算列,但 SQL Server 似乎没有使用它。如果我只使用带有索引的静态填充位列,我会得到预期的索引查找。
似乎还有其他一些类似的问题,但没有一个关注为什么不使用索引。
测试表:
CREATE TABLE dbo.Diffs
(
Id int NOT NULL IDENTITY (1, 1),
DataA int NULL,
DataB int NULL,
DiffPersisted AS isnull(convert(bit, case when [DataA] is null and [DataB] is not null then 1 when [DataA] <> [DataB] then 1 else 0 end), 0) PERSISTED ,
DiffComp AS isnull(convert(bit, case when [DataA] is null and [DataB] is not null then 1 when [DataA] <> [DataB] then 1 else 0 end), 0),
DiffStatic bit not null,
Primary Key (Id)
)
create index ix_DiffPersisted on Diffs (DiffPersisted)
create index ix_DiffComp on Diffs (DiffComp)
create index ix_DiffStatic on Diffs (DiffStatic)
Run Code Online (Sandbox Code Playgroud)
和查询:
select Id from Diffs where DiffPersisted = 1
select Id from Diffs where DiffComp = 1
select Id from Diffs where DiffStatic = 1
Run Code Online (Sandbox Code Playgroud)
Aar*_*and 10
尝试使用COALESCE
而不是ISNULL
. 使用ISNULL
,SQL Server 似乎无法针对更窄的索引推送谓词,因此必须扫描聚集的信息才能找到信息。
CREATE TABLE dbo.Diffs
(
Id int NOT NULL IDENTITY (1, 1),
DataA int NULL,
DataB int NULL,
DiffPersisted AS COALESCE(convert(bit, case when [DataA] is null
and [DataB] is not null then 1 when [DataA] <> [DataB]
then 1 else 0 end), 0) PERSISTED ,
DiffComp AS COALESCE(convert(bit, case when [DataA] is null
and [DataB] is not null then 1 when [DataA] <> [DataB]
then 1 else 0 end), 0),
DiffStatic bit not null,
Primary Key (Id)
);
Run Code Online (Sandbox Code Playgroud)
也就是说,如果您坚持使用静态列,过滤索引可能更有意义,并且 I/O 成本更低(这一切都取决于通常与过滤谓词匹配的行数),例如:
CREATE INDEX ix_DiffStaticFiltered
ON dbo.Diffs(DiffStatic)
WHERE DiffStatic = 1;
Run Code Online (Sandbox Code Playgroud)
这是 SQL Server 计算列匹配逻辑的特定限制,当使用最外层ISNULL
且列的数据类型为bit
.
为避免该问题,可以采用以下任何一种变通方法:
ISNULL
(制作计算列的唯一方法NOT NULL
)。bit
数据类型作为计算列的最终类型。PERSISTED
并启用跟踪标志 176。问题的核心是,如果没有跟踪标志 176,查询中的所有计算列引用(甚至是持久化的)总是在查询编译的早期扩展到底层定义中。
扩展的想法是它可以实现只能对定义起作用的简化和重写,而不能仅对列名起作用。例如,查询中可能存在引用该计算列的谓词,这可能会使部分计算变得多余,或者受到更多限制。
一旦考虑了早期的简化和重写,查询编译就会尝试将查询中的表达式与计算列(所有计算列,而不仅仅是那些最初在查询文本中找到的列)进行匹配。
在大多数情况下,未更改的计算列表达式匹配回原始计算列没有问题。当特定于匹配bit
类型表达式时,似乎存在一个错误,最外面的ISNULL
. 在这种特定情况下,匹配是不成功的,即使对内部结构的详细检查表明它应该成功。
归档时间: |
|
查看次数: |
1085 次 |
最近记录: |