我在SQL Server 2005中有以下非常大的表:
create table Blah
(
FirstName varchar(30),
Rank int,
Position int,
...
)
我将对其运行以下查询:
declare @PassedInFirstName varchar(30)
set @PassedInFirstName = 'SomeName'
select TOP 1 Position
from Blah
where FirstName = @PassedInFirstName
order by Rank DESC
我正在设置以下索引:
CREATE INDEX IX_Blah ON Blah (FirstName, Rank)
鉴于我是通过Rank DESC订购的,我是否应该将索引更改为按降序排列Rank:
CREATE INDEX IX_Blah ON Blah (FirstName ASC, Rank DESC)
或者没关系?
感谢。
答案 0 :(得分:3)
如果WHERE返回许多行,那么应该会受益。
通过在INDEX中使用DESC来匹配ORDER BY,我看到逻辑IO减少了50%的结果
此外,将查询更改为覆盖:
SQL 2005 +:
CREATE INDEX IX_Blah ON Blah (FirstName, Rank DESC) INCLUDE (Position)
SQL 2000,SQL 7:
CREATE INDEX IX_Blah ON Blah (FirstName, Rank DESC, Position)
答案 1 :(得分:2)
在索引中添加Rank作为降序值只是一个小改动。 Sql Server可以可能反转使用的排序,或者在这种情况下,很容易迭代到列表中的最后一项。
位置是您的主键吗?索引由索引列,主键和可选包含的列构成。如果Position不是您的主键,那么您当前正在索引中查找主键,然后使用主索引查找结果以寻找位置值。尝试将Position值添加为包含列,您应该能够仅基于一个索引执行查询,不会使用其他索引。
CREATE INDEX IX_Blah ON Blah (FirstName, Rank DESC) INCLUDE (Position)
别忘了查看您的查询计划,他们可以告诉您是否缺少任何索引(假设是Sql Server 2008),使用了哪些索引等等。
答案 2 :(得分:0)
我在上一篇文章中搞砸了身份验证,这是我的注册用户。
索引基于您选择的列和主键。您基本上存储了一个hashmap,其中键(FirstName,Rank)解析为您的Id(假设您的主键是Id)。然后使用此Id读取位置值。
我的主张是将Position值作为包含列包含在索引中。这将允许您从索引中读取数据,避免第二次查找。