1. 全值匹配
示例:
表中根据class,score,total字段建立联合索引 idx_class_score_total
上述结果发现:两条sql的执行结果是一致的,所以当根据这三个字段查询数据时都可以命中索引无论顺序;
是不是又有一个疑问?为什么打乱顺序也可以命中索引?
mysql中的查询优化器会纠正这条sql语句该以哪种顺序执行效率最高,最后生成真正的执行计划(QEP),尽量利用到索引时查询顺序效率最高。所以mysql查询优化器最终会以(a_b_c)这种顺序查询,所以b_a_c可以命中索引;
【注】
当查询语句为 select * from test where class=1 and total>1 and score=1;
只要查询字段包含了索引的所有字段(全值匹配),那么优化器就先会调整位置,将>调整至最后;
2. 最佳左前缀法则
建立索引
CREATE INDEX idx_age_deptid_name ON emp(age,deptid,NAME);
查询字段与索引字段顺序的不同会导致,索引无法充分使用,甚至索引失效!
原因:使用复合索引,需要遵循最佳左前缀法则,即如果索引了多列,要遵守最左前缀法则。指的是查询从索引的最左前列开始并且不跳过索引中的列。
结论:过滤条件要使用索引必须按照索引建立时的顺序,依次满足,一旦跳过某个字段,索引后面的字段都无法被使用。
3. 不要在索引列上做任何计算
不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描。
示例:
EXPLAIN SELECT SQL_NO_CACHE FROM emp WHERE age=30;
EXPLAIN SELECT SQL_NO_CACHE FROM emp WHERE LEFT(age,3)=30;
【注】
自动或手动类型转换,比如当name是varchar类型,但是where条件不小心写成了int类型,他能查询成功,系统能自动帮你类型转换。但是会导致索引失效。
4. 索引列上不能有范围查询
5. 尽量使用覆盖索引
即查询列和索引列一致,不要写select *!
覆盖索引
6. 使用不等于(!= 或者<>)的时候
mysql 在使用不等于(!= 或者<>)时,有时会无法使用索引会导致全表扫描。
7. 字段的is not null 和is null

【注】
针对这个点:有不同说法
1、当索引字段不可以为null 时,只有使用is not null 返回的结果集中只包含索引字段时,才使用索引
2、当索引字段可以为空时,使用 is null 不影响覆盖索引,但是使用 is not null 只有完全返回索引字段时才会使用索引
8. like 的前后模糊匹配
9. 减少使用or
10. 练习
11. 口诀
全职匹配我最爱,最左前缀要遵守;
带头大哥不能死,中间兄弟不能断;
索引列上少计算,范围之后全失效;
LIKE 百分写最右,覆盖索引不写*;
不等空值还有OR,索引影响要注意;
VAR 引号不可丢,SQL 优化有诀窍。




