我的数据库中有下表:
create table [dbo].[tb_StatusLog](
[RequestID] [int] not null,
[statusID] [int] not null,
[startTime] [datetime] not null,
[endTime] [datetime] null,
)
具有以下非聚集索引
create nonclusteredindex [index1] on [dbo].[tb_StatusLog]
(
requestID asc,
statusID asc
)
include ([startTime])
和下面的表值函数fn_getTable
select requestID, max(startTime)
from tb_StatusLog
where statusID=2
group by requestID, statusID
在运行探查器跟踪并通过 db engine tuning advisor 运行结果后,它建议我创建以下索引(这与我拥有的索引相同,但键列颠倒了):
create nonclusteredindex [index2] on [dbo].[tb_StatusLog]
(
statusID asc,
requestID asc
)
include ([startTime])
现在,运行时fn_getTable
,执行计划使用index2
而不是index1
性能提高。
这是为什么?
因为您在 上有一个相等谓词
where statusID=2
。使用相反的顺序,它能够精确地查找与状态匹配的行,然后这些行可以馈送到流聚合中以进行分组。
您的原始索引支持
group by requestID, statusID
但不支持WHERE
- 这意味着将需要扫描整个索引并且仅匹配statusID=2
保留的行。有点简化,但您可以将复合索引想象成行首先按第一列排序,然后按第二列排序,依此类推。你的第一个例子是:
要查找 statusId=2 的行,无法确定从哪里开始,必须扫描整个索引。与之比较:
DBMS 可以从 (2,A) 开始,读取另一个条目 (2,B) 并完成它。