拥有多年的 DBA 经验,我相信我知道问题的答案,但我认为检查我的基础永远不会有坏处。
使用 SQL Server,假设我有一个表,它在 columnA
和 column上有一个索引B
,在 columns A
、B
和上有一个第二个索引C
,删除第一个索引是否安全,因为第二个索引基本上会满足将从中受益的查询第一个索引?
拥有多年的 DBA 经验,我相信我知道问题的答案,但我认为检查我的基础永远不会有坏处。
使用 SQL Server,假设我有一个表,它在 columnA
和 column上有一个索引B
,在 columns A
、B
和上有一个第二个索引C
,删除第一个索引是否安全,因为第二个索引基本上会满足将从中受益的查询第一个索引?
这取决于,但答案通常是“是的,您可以将索引放在 (A,B) 上”。
反例(您不会删除 (A,B) 上的索引)是当 (A,B) 上的索引是强制执行约束的唯一索引时;那么您不想在 (A,B) 上删除索引。(A,B,C) 上的索引也可以是唯一的,但唯一性是多余的,因为 (A,B) 组合是唯一的,因为另一个索引。
但是在没有这种异常情况的情况下(例如,如果 (A,B) 和 (A,B,C) 都允许重复条目),则 (A,B) 索引在逻辑上是多余的。但是,如果列 C 是“宽”列(可能是 CHAR(100) 列),而 A 和 B 很小(比如 INTEGER),则 (A,B) 索引比 (A,B,C) 更有效) 索引,因为您可以获得 (A,B) 索引的每页读取的更多信息。因此,即使 (A,B) 是多余的,它也可能值得保留。您还需要考虑表格的波动性;如果表很少更改,则额外的索引无关紧要;如果表变化很大,额外的索引会减慢对表的修改。这是否重要很难猜测。您可能需要进行性能测量。
第一个索引涵盖在 上查找的查询,A
第二A,B
个索引可用于涵盖在 上查找的查询A
,A,B
或者A,B,C
显然是第一种情况的超集。
IfC
非常宽,但是索引A,B
可能仍然有用,因为它可以用更少的读取来满足某些查询。
例如,如果C
是一char(800)
列,则以下查询可能会因提供更窄的索引而受益匪浅。
SELECT a,b
FROM YourTable
ORDER BY a,b
是的,这是一个常见的优化。任何将从 A、B 上的索引中受益的查询也可以从 A、B、C 上的索引中受益。
在 MySQL 社区中,甚至还有一个工具可以在整个架构中搜索冗余索引: http ://www.percona.com/doc/percona-toolkit/pt-duplicate-key-checker.html
可能的例外情况是,如果 A、B 上的索引更紧凑且使用更频繁,并且您想控制哪个索引保持加载在内存中。
我在想的大部分内容都是乔纳森在之前的回答中写的。独特性,更快的工作,以及我认为他错过的另一件事。
如果第一个索引是A desc, B asc
第二个A asc, B asc, C asc
,那么删除第一个索引并不是真正可行的方法,因为第二个索引不是第一个索引的超集,如果排序为,您的查询不能从第二个索引中受益写在第一个。
在某些情况下,例如当您使用第一个索引时,您可以order by A desc, B asc
(当然) and A asc, B desc
,但您也可以进行查询以使用该索引的任何部分,例如Order by A desc
.
但是像order by A asc, B asc
, 这样的查询不会被第一个索引“覆盖”。
所以我想加起来,您通常可以删除第一个索引,但这取决于您的表配置和查询(当然还有索引)。
我通常会在包含历史数据的表中找到这个“几乎”相似的索引。如果column C
是日期或整数列,请小心。它最有可能用于满足 MAX 中的函数WHERE tblA.C = MAX(tblB.C)
,它完全跳过表并使用仅索引访问路径。