正如Remus所说,这取决于你的工作量。
不过,我想指出公认答案的误导方面。
对于在索引中的所有列上执行相等搜索的查询,没有显著差异。
下面创建两个表并用相同的数据填充它们。唯一的区别是,一个键的顺序从最多到最少,另一个则相反。
CREATE TABLE Table1(MostSelective char(800), SecondMost TINYINT, Least CHAR(1), Filler CHAR(4000) null);
CREATE TABLE Table2(MostSelective char(800), SecondMost TINYINT, Least CHAR(1), Filler CHAR(4000) null);
CREATE NONCLUSTERED INDEX MyINDX on Table1(MostSelective,SecondMost,Least);
CREATE NONCLUSTERED INDEX MyINDX2 on Table2(Least,SecondMost,MostSelective);
INSERT INTO Table1 (MostSelective, SecondMost, Least)
output inserted.* into Table2
SELECT TOP 26 REPLICATE(CHAR(number + 65),800), number/5, '~'
FROM master..spt_values
WHERE type = 'P' AND number >= 0
ORDER BY number;
现在对这两个表进行查询……
SELECT *
FROM Table1
WHERE MostSelective = REPLICATE('P', 800)
AND SecondMost = 3
AND Least = '~';
SELECT *
FROM Table2
WHERE MostSelective = REPLICATE('P', 800)
AND SecondMost = 3
AND Least = '~';
... 两者都使用指数罚款,两者的成本完全相同。
公认答案中的ASCII艺术实际上并不是索引的结构。表1的索引页如下所示(单击图像以全尺寸打开)。
索引页包含包含整个键的行(在这种情况下,实际上有一个额外的键列附加为行标识符,因为索引没有声明为唯一的,但可以忽略关于此的进一步信息,可以在这里找到)。
对于上面的查询,SQL Server不关心列的选择性。它对根页面进行二进制搜索,并发现Key (PPP…,3,~)是>=(JJJ…,1,~)和< (SSS…,3,~)所以应该读第1页118。然后,它对该页上的关键项进行二进制搜索,并定位要向下移动到的叶页。
按照选择性的顺序更改索引既不会影响二元搜索中键比较的预期数量,也不会影响进行索引查找所需导航的页面数量。最好的情况下,它可能会略微加快键比较本身。
不过,有时优先排序最具选择性的索引对于工作负载中的其他查询是有意义的。
例如,如果工作负载包含以下两种表单的查询。
SELECT * ... WHERE MostSelective = 'P'
SELECT * ...WHERE Least = '~'
上面的指数并没有涵盖这两种情况。MostSelective具有足够的选择性,使得包含查找和查找的计划有价值,但针对Least的查询则没有。
然而,这种情况(对复合索引的主列子集进行非覆盖索引查找)只是索引可以帮助的一种可能的查询类别。如果你从来没有通过MostSelective或MostSelective和SecondMost的组合来搜索,而总是通过这三列的组合来搜索,那么这个理论上的优势对你来说是没有用的。
相反,查询如下
SELECT MostSelective,
SecondMost,
Least
FROM Table2
WHERE Least = '~'
ORDER BY SecondMost,
MostSelective
如果使用与通常指定的顺序相反的顺序,则会有所帮助-因为它涵盖了查询,可以支持seek并以所需的顺序返回行以引导。
因此,这是一个经常被重复的建议,但最多只是关于其他查询的潜在好处的启发式——它不能替代实际查看您的工作量。