在SQL Server(以及大多数其他关系数据库)中,“复合索引”是一个具有多个键的索引。假设我们有一个经常运行的查询,我们想为这个查询创建一个覆盖索引来加速它;SELECT a, b FROM MyTable WHERE c = @val1 AND d = @val2
这些都是将覆盖此查询的可能的复合索引;
CREATE INDEX ix1 ON MyTable (c, d, a, b)
CREATE INDEX ix2 ON MyTable (c, d) INCLUDE (a, b)
CREATE INDEX ix3 ON MyTable (d) INCLUDE (a, b, c)
CREATE INDEX ix4 ON MyTable (c) INCLUDE (a, b, d)
但显然,它们的表现并不一样,根据Erlan Sommarskog (Microsoft MVP),前两个比第三和第四个快,第四个比第三个快。
他接着解释说;
ix 2是“最好的”索引,因为a和b不会占用索引树较高级别的空间,而且,如果a或b被更新,在ix 2中可能没有页面拆分或类似操作,因为索引树不受影响。
然而,我很难理解到底发生了什么。我确实对b树索引及其工作原理有一些了解,但我不理解组合键背后的逻辑。CREATE INDEX ix1 ON MyTable (c, d, a, b)
列的顺序重要吗?如果重要,为什么?还有;CREATE INDEX ix2 ON MyTable (c, d) INCLUDE (a, b)
这个组合键和上面的组合键有什么区别?我不明白“INCLUDE”有什么区别。
注意:我知道有很多关于组合键的帖子,但我相信我的最后两个问题足够具体,不会重复。
2条答案
按热度按时间yhqotfr81#
这里列的顺序重要吗?
仅考虑问题中具有2个相等 predicate 的查询,只要这两个关键字列都是复合索引的最左侧关键字列,则复合索引关键字列的顺序并不重要。下面的任何覆盖索引都将优化此查询:
也就是说,统计信息直方图只包含最左边的索引关键字列,因此一般指导是首先指定选择性最强的列,以提高行计数估计值和执行计划质量。对于优化程序有许多选择的非平凡查询,此考虑因素更为重要,而行计数估计值是选择最佳计划的一个重要因素。
键顺序的另一个注意事项可能与上述一般指导相冲突,即索引支持不同的查询并且只指定了某些键列(例如
SELECT a, b FROM MyTable WHERE d = @val2;
)。在这种情况下,最好将d
指定为最左边的列,而不考虑选择性,以便允许单个索引优化多个查询,而不是创建单独的索引进行优化第二个查询。这个组合键和上面的组合键有什么区别?我不明白"INCLUDE"有什么区别。
包含的列不是关键字列。关键字列在整个b树的每个级别上都按逻辑顺序维护,而包含的列只出现在b树的叶节点中,并且没有排序。因此,包含的列的指定顺序并不重要。包含的列的唯一用途是帮助覆盖查询,而不将其添加为关键字列并产生相关的开销。
z31licg02#
列的顺序重要吗?如果重要,为什么?还有;
是的,在创建索引时,顺序非常重要,因为每一列(从左起)都是索引中的下一个深度级别,所以要确定编译器使用这个索引,你需要总是寻找c,它是这个集合的"打开者"。
这个组合键和上面的组合键有什么区别?我不明白"INCLUDE"有什么区别。
但是请记住,对于索引的每一层,它的效率都开始降低,所以如果你知道超过80%的查询只会通过c & d而不是a & b来查找,但是你需要在SELECT中(也不需要在WHERE中)包含这些信息,你应该将它们作为索引最后一层的叶子的一部分。
有比我更好的解释,所以请随意看看他们:
INCLUDE equivalent in Oracle-〉包含How important is the order of columns in indexes?-〉索引集合中的顺序