应该删除 MySQL 中的“重复”索引吗?

Rag*_*age 5 mysql sql database database-design

我知道在 MySQL 索引 (A,B,C) 中,使用 |A|、|A、B|、|A、B、C| 的 ANDed WHERE 子句受益。这使得看起来拥有索引 (A,B,C) 意味着在 (A) 上拥有单个索引或在 (A,B) 上拥有复合索引是没有意义的。

1. 这是真的吗?

2. 当你已经有 (A,B,C) 的索引时,在 (A) 上维护索引只是一种浪费吗?

Tim*_*imo 2

我相信你的两个问题的答案是相同的:几乎完全正确;在 (A, B, C) 和 (A) 上都建立索引几乎总是浪费。

正如丹布莱克提到的,尺寸可能会产生微小的差异,尽管这可能可以忽略不计。

更重要的是,根据我的经验,请注意 (A) 实际上是 (A, Primary),其中 Primary 是那些尚未显式包含在索引中的主键列。实际上,这通常意味着(A,Id)。那么,另一个索引实际上是(A,B,C,Id)。请注意这如何影响索引中遇到行的顺序。

想象一下这样做:

SELECT *
FROM MyTable
WHERE A = 'Whatever'
ORDER BY Id
Run Code Online (Sandbox Code Playgroud)

索引 (A),又称为 (A,Id),非常适合此目的。对于 A 的任何固定值,相应的行将按 Id 排序。不需要排序 - 结果按照我们想要的顺序排列。

然而,对于索引(A,B,C),AKA(A,B,C,Id),情况有所不同。对于 A 的任何固定值,相应的行将按 B 排序!这意味着上述查询将需要对结果进行排序。

EXPLAIN应该证实我所描述的内容。如果只有 (A, B, C) 索引可用,则Afilesort会发生,但如果 (A) 可用,则 A 不会发生。

应该很容易看出,如果 A 的特定值通常只有很少的行,那么这并不重要。但是,如果这样的值可能有 100,000 行,那么就会开始产生filesort影响。在这种情况下,您可以选择使用索引 (A) 来针对此场景进行优化。

一般来说,这样的前缀索引是多余的。不过,最好分析您的索引和查询来识别这些场景。在极少数情况下,可能值得添加一个。在更常见的情况下,至少您将能够在整体指数选择中权衡此类影响。