Abe*_*ler 155 sql t-sql sql-server indexing sql-server-2005
我听说你应该在索引声明的开头放置最具选择性的列.例:
CREATE NONCLUSTERED INDEX MyINDX on Table1
(
MostSelective,
SecondMost,
Least
)
Run Code Online (Sandbox Code Playgroud)
首先,我说的是正确的吗?如果是这样,我可能会通过重新排列索引中列的顺序来看到性能上的巨大差异,还是更像是"很好做"的做法?
我问的原因是因为在通过DTA进行查询后,它建议我创建一个索引,其中几乎所有列都与现有索引相同,只是顺序不同.我正在考虑将缺少的列添加到现有索引并调用它.思考?
Nic*_*ver 181
看一下像这样的索引:
Cols
1 2 3
-------------
| | 1 | |
| A |---| |
| | 2 | |
|---|---| |
| | | |
| | 1 | 9 |
| B | | |
| |---| |
| | 2 | |
| |---| |
| | 3 | |
|---|---| |
Run Code Online (Sandbox Code Playgroud)
首先看一下如何限制A,因为您的第一列消除了比首先限制第二列更多的结果?如果您想象索引必须如何遍历,第1列,然后是第2列等,那么就会更容易...您会看到在第一次通过中砍掉大部分结果会使第2步更快.
另一种情况,如果您在第3列上查询,优化器甚至不会使用索引,因为它在缩小结果集方面没有任何帮助. 无论何时进行查询,在下一步骤之前缩小要处理的结果数量意味着更好的性能.
由于索引也以这种方式存储,因此当您查询索引时,索引中没有回溯以查找第一列.
简而言之:不,它不是为了表演,有真正的性能优势.
Rem*_*anu 118
列的顺序至关重要.现在哪个订单是正确的,这取决于您将如何查询它.索引可用于执行精确搜索或范围扫描.精确搜索是指定索引中所有列的值并且查询准确归位于行感兴趣的时间.对于搜索,列的顺序无关紧要.范围扫描是指定只有一些列,在这种情况下,当订单变得重要时.仅当指定了最左侧的列时,SQL Server才能使用索引进行范围扫描,然后仅在指定了下一个最左侧的列时才使用索引,依此类推.如果您对(A,B,C)的索引可以用来范围扫描A=@a,为A=@a AND B=@b但不为B=@b,对于C=@c也不B=@b AND C=@c.案例A=@a AND C=@c是混合的,因为在A=@a部分将使用索引,但C=@c不是(查询将扫描所有B值A=@a,不会'跳过' C=@c).其他数据库系统具有所谓的"跳过扫描"运算符,当未指定外部列时,该运算符可以利用索引中的内部列.
掌握了这些知识,您可以再次查看索引定义.索引(MostSelective, SecondMost, Least)将仅在MostSelective指定列时有效.但这是最具选择性的,内部列的相关性将迅速降低.通常,您会发现更好的索引正在开启(MostSelective) include (SecondMost, Least)或开启(MostSelective, SecondMost) include (Least).因为内部列不太相关,所以在索引中的这些正确位置放置低选择性列使得它们只是搜索的噪声,因此将它们移出中间页面并将它们仅保留在叶页上是有意义的,因为查询可覆盖性目的.换句话说,将它们移动到INCLUDE.随着Least列的大小增加,这变得更加重要.我们的想法是,这个索引只能使指定MostSelective为精确值或范围的查询受益,并且该列是最具选择性的,它已经在很大程度上限制了候选行.
另一方面,索引(Least, SecondMost, MostSelective)似乎是一个错误,但它实际上是一个非常强大的指数.因为它将Least列作为其最外层查询,所以它可以用于必须在低选择性列上聚合结果的查询.此类查询在OLAP和分析数据仓库中很普遍,而这正是这些索引具有非常好的案例的地方.这样的索引实际上是优秀的聚簇索引,正是因为它们在大块相关行(相同的Least值,通常表示某种类别或类型)上组织物理布局,并且它们便于分析查询.
所以,不幸的是,没有'正确'的顺序.您不应该遵循任何cookie切割器配方,而是分析您将要对这些表使用的查询模式,并确定哪个索引列顺序正确.
Mar*_*ith 43
正如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;
Run Code Online (Sandbox Code Playgroud)
现在对两个表进行查询......
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 = '~';
Run Code Online (Sandbox Code Playgroud)
...他们都使用索引罚款,两者都给出完全相同的成本.
接受的答案中的ASCII艺术实际上并不是索引的结构.Table1的索引页面如下所示(单击图像以完整大小打开).
索引页面包含包含整个键的行(在这种情况下,实际上为行标识符附加了一个附加键列,因为索引未声明为唯一但可以忽略此处的更多信息可在此处找到).
对于上面的查询,SQL Server不关心列的选择性.它对根页进行二进制搜索,发现密钥 (PPP...,3,~ )是>=(JJJ...,1,~ ),< (SSS...,3,~ )因此它应该读取页面1:118.然后,它对该页面上的键条目进行二进制搜索,并找到向下移动的叶子页面.
按选择性顺序更改索引不会影响二进制搜索的预期密钥比较次数或需要导航以进行索引查找的页面数.充其量它可能会略微加快关键比较本身.
有时,首先排序最具选择性的索引对于工作负载中的其他查询也是有意义的.
例如,如果工作负载包含以下两种形式的查询.
SELECT * ... WHERE MostSelective = 'P'
SELECT * ...WHERE Least = '~'
Run Code Online (Sandbox Code Playgroud)
上述指数并未涵盖其中任何一项.MostSelective是有选择性的,足以制定一个寻求和查找有价值的计划,但查询Least不是.
然而,这种情况(非覆盖索引寻找复合索引的前导列的子集)只是一个可以由索引帮助的可能的查询类.如果您从未实际搜索过MostSelective它自己或其组合MostSelective, SecondMost并始终通过所有三列的组合进行搜索,那么这种理论优势对您来说毫无用处.
相反的查询,如
SELECT MostSelective,
SecondMost,
Least
FROM Table2
WHERE Least = '~'
ORDER BY SecondMost,
MostSelective
Run Code Online (Sandbox Code Playgroud)
通过使用通常规定的相反顺序(因为它涵盖了查询),可以支持查找并以所需顺序返回行以启动.
所以这是一个经常重复的建议,但最多它是关于其他查询的潜在好处的启发式方法- 它实际上无法替代实际查看您的工作量.
OMG*_*ies 30
你应该在索引声明的开头放置最具选择性的列.
正确.索引可以是复合 - 由多列组成 - 由于最左边的原则,顺序很重要.原因是,数据库从左到右检查列表,并且必须找到与定义的顺序匹配的相应列引用.例如,在具有列的地址表上具有索引:
使用该address列的任何查询都可以使用索引,但如果查询只有一个city和/或state引用 - 则无法使用索引.这是因为没有引用最左边的列.查询性能应该告诉您哪个是最优的 - 单个索引,或具有不同顺序的多个组合.好读:金伯利·特里普的引爆点
选择性是一个非常小的因素;“最左边”是关键
选择顺序时,复合索引中各个列的选择性无关紧要。
这是一个简单的思考过程: 实际上,索引是所涉及的列的串联。
给出这个基本原理,唯一的区别是比较字符串中较早与较晚不同的两个“字符串”。这只是总成本的一小部分。正如一个答案中提到的那样,没有“第一次通过/第二次通过”。
那么,应该使用什么顺序呢?
=以任何顺序从用,测试的列开始。例如,极低选择性列必须排在第一位:
WHERE deleted = 0 AND the_datetime > NOW() - INTERVAL 7 DAY
INDEX(deleted, the_datetime)
Run Code Online (Sandbox Code Playgroud)
交换索引中的顺序将使其完全忽略deleted。
(对列进行排序有更多规则。)
| 归档时间: |
|
| 查看次数: |
76628 次 |
| 最近记录: |