MySQL 联合索引创建指南
实际的开发过程当中为 MySQL 建立联合索引是无法避免的。但是考虑到最左匹配原则和一些索引失效的场景,建立索引仍然存在一些技巧。本文将给出一些简单的场景,根据这些场景来讨论如何创建 MySQL 联合索引是最有效的。
WHERE a = 1 AND b = 2 AND c = 3
SELECT * FROM <table> WHERE a = 1 AND b = 2 AND c = 3;
可以注意到 WHERE
语句中的三个限制条件都是 =
,不会引起索引的失效。所以建立 (a, b, c)、(c, b, a) 或者 (b, a, c) 三种联合索引都可以。重点要的是将区分度高的字段放在前面,区分度低的字段放后面。像性别、状态这种字段区分度就很低,我们一般放后面。
WHERE a > 1 AND b = 2
SELECT * FROM <table> WHERE a > 1 AND b = 2;
由于 >
会引起索引的失效,根据最左匹配原则,我们应该对 (b, a) 建立索引。如果你建立的是 (a, b) 索引,那么只有 a 字段能用得上索引,毕竟最左匹配原则遇到范围查询就停止匹配。
如果对 (b, a) 建立索引那么两个字段都能用上,优化器会帮我们调整 WHERE
后 a 和 b 的顺序,让我们用上索引。
WHERE a > 1 AND b = 2 AND c > 3
SELECT * FROM <table> WHERE a > 1 AND b = 2 AND c > 3;
跟上一个场景类似,这种情况下建立 (b, a) 或者 (b, c) 都可以。
WHERE a = 1 ORDER BY b
SELECT * FROM <table> WHERE a = 1 ORDER BY b;
此时应该对 (a, b) 建索引。因为这样在索引树中当 a = 1 的时候,b 相对有序,可以避免再次排序。
WHERE a > 1 ORDER BY b
SELECT * FROM <table> WHERE a > 1 ORDER BY b;
跟上一个场景不同的是,这一次 a 字段是范围查询,这个范围内 b 值是无序的。所以我们应该对 (a) 建立索引,没有必要对 (a, b) 建立索引。
WHERE a = 1 AND b = 2 AND c > 3 ORDER BY c
SELECT * FROM <table> WHERE a = 1 AND b = 2 AND c > 3 ORDER BY c;
这种场景下应该对 (a, b, c) 建立索引。c 字段也包含进去可以避免重新的排序。
WHERE a IN (1, 2, 3) AND b > 1
SELECT * FROM <table> WHERE a IN (1, 2, 3) AND b > 1;
对 (a,b) 建立索引。因为 IN
在这里可以视为等值引用,不会中止索引匹配。