正如 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 艺术实际上并不是索引的结构。 Table1 的索引页如下所示(点击图片以全尺寸打开)。
索引页包含包含整个键的行(在这种情况下,实际上为行标识符附加了一个附加键列,因为索引未声明为唯一但可以忽略further information about this can be found here)。
对于上面的查询,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
如果使用通常规定的顺序相反的顺序会有所帮助 - 因为它涵盖了查询,可以支持查找并以启动所需的顺序返回行。
所以这是一条经常重复的建议,但最多只是对其他查询的潜在好处的启发式 - 它不能替代实际查看您的工作量。