选择INCLUDE 而不是键列如果您不需要键中的该列 的一个原因是文档。这使得未来不断发展的索引变得更加容易。
考虑你的例子:
CREATE INDEX idx1 ON MyTable (Col1) INCLUDE (Col2, Col3)
如果您的查询如下所示,则该索引是最好的:
SELECT col2, col3
FROM MyTable
WHERE col1 = ...
当然,如果您可以从将列放在关键部分中获得额外的好处,那么您不应该将列放在 INCLUDE 中。以下两个查询实际上都更喜欢索引键中的col2 列。
SELECT col2, col3
FROM MyTable
WHERE col1 = ...
AND col2 = ...
SELECT TOP 1 col2, col3
FROM MyTable
WHERE col1 = ...
ORDER BY col2
假设情况不是,我们在INCLUDE 子句中有col2,因为将它放在索引的树部分没有任何好处。
快进几年。
您需要调整此查询:
SELECT TOP 1 col2
FROM MyTable
WHERE col1 = ...
ORDER BY another_col
要优化该查询,以下索引会很棒:
CREATE INDEX idx1 ON MyTable (Col1, another_col) INCLUDE (Col2)
如果您检查该表上已有的索引,则您之前的索引可能仍然存在:
CREATE INDEX idx1 ON MyTable (Col1) INCLUDE (Col2, Col3)
现在您知道Col2 和Col3 不是索引树的一部分,因此既不用于缩小读取索引范围,也不用于对行进行排序。将another_column 添加到索引键部分的末尾(col1 之后)是相当安全的。破坏任何东西的风险很小:
DROP INDEX idx1 ON MyTable;
CREATE INDEX idx1 ON MyTable (Col1, another_col) INCLUDE (Col2, Col3);
那个索引会变大,还是有一定风险的,但是一般来说扩展现有索引比引入新索引要好。
如果您有一个没有INCLUDE 的索引,您不知道在Col1 之后添加another_col 会破坏哪些查询。
CREATE INDEX idx1 ON MyTable (Col1, Col2, Col3)
如果在Col1 和Col2 之间添加another_col 会发生什么?其他查询会受到影响吗?
INCLUDE 与关键列相比还有其他“好处”如果您添加这些列只是为了避免从表中获取它们。但是,我认为文档方面最重要。
回答你的问题:
在确定是否创建包含或不包含 INCLUDE 子句的覆盖索引时,您会提出哪些建议?
如果您向索引添加列的唯一目的是使该列在索引中可用而不访问该表,请将其放入INCLUDE 子句中。
如果将列添加到索引键会带来额外的好处(例如,对于order by 或因为它可以缩小读取索引范围)将其添加到键中。
您可以在此处阅读更长的讨论:
https://use-the-index-luke.com/blog/2019-04/include-columns-in-btree-indexes