EXPLAIN SELECT * FROM staff WHERE name= 'zhangsan' AND work_age = 2;
EXPLAIN SELECT * FROM staff where name = 'zhangsan' AND work_age = 2 AND position = 'dev';
EXPLAIN SELECT * FROM staff where position = 'dev' AND name = 'zhangsan' AND work_age = 2;
最后一条,我们将 position 放到了 WHERE 条件后面,尽管没有按照联合索引的顺序编写条件,MySQL 优化器会自动优化,将 name 排到最前面去,所以还是会正确使用联合索引的。
联合索引创建后,你必须严格按照最左前缀的原理进行使用,否则会无法使用到索引。尽量按照这个顺序去写,这样避免 MySQL 优化器再次优化了。
2、最佳左前缀法则:
如果索引了多列,要遵守最左前缀法则。指的是查询从索引的最左前列开始并且不跳过索引中的列。
以下 SQL 符合最左前缀匹配法则:
EXPLAIN SELECT * FROM staff WHERE name = 'zhangsan' AND work_age = 3 AND position = 'manager';
EXPLAIN SELECT * FROM staff WHERE name = 'zhangsan' AND position = 'manager';
以下执行都是全表扫描,type 为 ALL,都不符合最左前缀法则:
EXPLAIN SELECT * FROM staff WHERE work_age = 2 AND position ='dev';
EXPLAIN SELECT * FROM staff WHERE position = 'dev';
3、索引列上避免做计算操作
索引上尽量避免做函数计算等操作,会导致索引失效而转向全表扫描。
WHERE 条件后面索引列使用函数:
EXPLAIN SELECT * FROM staff WHERE LEFT(name, 5) = 'zhang';
EXPLAIN SELECT * FROM staff WHERE LOWER(name) = 'zhangsan';
EXPLAIN SELECT * FROM staff WHERE staff.s_no * 2 > 3;
查询的结果 type 列为 ALL,key 是空的,索引失效,全表扫描。
计算逻辑尽量放到业务层去处理,最大限度的命中索引,同时还能节省数据库资源开销。
4、存储引擎无法使用索引中范围条件右边的列
EXPLAIN SELECT * FROM staff WHERE name= 'zhangsan' AND work_age > 2 AND position ='dev';