关于索引

【老叶观点】除了常见的建议外,还有几个要点:html

7.一、超过20个长度的字符串列,最好建立前缀索引而非整列索引(例如:ALTER TABLE t1 ADD INDEX(user(20))),能够有效提升索引利用率,不过它的缺点是对这个列排序时用不到前缀索引。前缀索引的长度能够基于对该字段的统计得出,通常略大于平均长度一点就能够了。mysql

7.二、按期用 pt-duplicate-key-checker 工具检查并删除重复的索引。好比 index idx1(a, b) 索引已经涵盖了 index idx2(a),就能够删除 idx2 索引了。sql

7.三、有多字段联合索引时,WHERE中过滤条件的字段顺序无需和索引一致,但若是有排序、分组则就必须一致了。session

好比有联合索引 idx1(a, b, c),那么下面的SQL均可以完整用到索引:工具

SELECT ... WHERE b = ? AND c = ? AND a = ?;  --注意到,WHERE中字段顺序并无和索引字段顺序一致
SELECT ... WHERE b = ? AND a = ? AND c = ?;
SELECT ... WHERE a = ? AND b IN (?, ?) AND c = ?;
SELECT ... WHERE a = ? AND b = ? ORDER BY c;
SELECT ... WHERE a = ? AND b IN (?, ?) ORDER BY c;
SELECT ... WHERE a = ? ORDER BY b, c;
SELECT ... ORDER BY a, b, c;  -- 可利用联合索引完成排序

而下面几个SQL则只能用到部分索引,或者可利用到ICP特性:优化

SELECT ... WHERE b = ? AND a = ?; -- 只能用到 (a, b) 部分
SELECT ... WHERE a IN (?, ?) AND b = ?; -- EXPLAIN显示只用到 (a, b) 部分索引,同时有ICP
SELECT ... WHERE (a BETWEEN ? AND ?) AND b = ?; -- EXPLAIN显示只用到 (a, b) 部分索引,同时有ICP
SELECT ... WHERE a = ? AND b IN (?, ?); -- EXPLAIN显示只用到 (a, b) 部分索引,同时有ICP
SELECT ... WHERE a = ? AND (b BETWEEN ? AND ?) AND c = ?; -- EXPLAIN显示用到 (a, b, c) 整个索引,同时有ICP
SELECT ... WHERE a = ? AND c = ?; -- EXPLAIN显示只用到 (a) 部分索引,同时有ICP
SELECT ... WHERE a = ? AND c >= ?; -- EXPLAIN显示只用到 (a) 部分索引,同时有ICP

ICP(index condition pushdown)是MySQL 5.6的新特性,其机制会让索引的其余部分也参与过滤,减小引擎层和server层之间的数据传输和回表请求,一般状况下可大幅提高查询效率。

下面的几个SQL彻底用不到该索引:code

SELECT ... WHERE b = ?;
SELECT ... WHERE b = ? AND c = ?;
SELECT ... WHERE b = ? AND c = ?;
SELECT ... ORDER BY b;
SELECT ... ORDER BY b, a;

从上面的几个例子就能看的出来,以往强调的WHERE条件字段顺序要和索引顺序一致才能使用索引的 “常识性误导” 无需严格遵照。server

此外,有些时候查询优化器指定的索引或执行计划可能并非最优的,能够手工指定最优索引,或者修改session级的 optimizer_switch 选项,关闭某些致使效果反而更差的特性(好比index merge一般是好事,但也遇到过用上index merge后反而更差的,这时候要么强制指定其中一个索引,要么能够临时关闭 index merge 特性)。htm

相关文章
相关标签/搜索