1. 最左前缀法则
2. 范围查询
解决办法是 替换为>=或者<=来规避索引失效问题。
3. 索引列运算
如:explain select * from tb_user where substring(phone, 10, 2) = '15';
4. 字符串不加引号
如:explain select * from tb_user where phone = 17799990015;
,此处phone的值没有加引号
5. 模糊查询
如:explain select * from tb_user where profession like '%工程';
,前后都有 % 也会失效。
6. or连接的条件
7. 数据分布影响
8. SQL提示
例如,使用索引
explain select * from tb_user use index(idx_user_pro) where profession="软件工程";
#use 是建议,实际使用哪个索引 MySQL 还会自己权衡运行速度去更改
指定不使用哪个索引
explain select * from tb_user ignore index(idx_user_pro) where profession="软件工程";
指定必须使用哪个索引
explain select * from tb_user force index(idx_user_pro) where profession="软件工程";
#force是无论如何都强制使用该索引
9. 覆盖索引
举例说明
explain 中 extra 字段含义:
using index condition
:查找使用了索引,但是需要回表查询数据
using where; using index;
:查找使用了索引,但是需要的数据都在索引列中能找到,所以不需要回表查询
结合上图实际情况
覆盖索引&回表查询过程举例说明
执行SQL : select * from tb_user where id = 2;
执行SQL:selet id,name from tb_user where name = ‘Arm’;
执行SQL:selet id,name,gender from tb_user where name = ‘Arm’;
面试题:一张表,有四个字段(id, username, password, status),由于数据量大,需要对以下SQL语句进行优化,该如何进行才是最优方案?
select id, username, password from tb_user where username='itcast'; 解:给username和password字段建立联合索引,则不需要回表查询,直接覆盖索引 123
- 1
- 2
- 3
- 4
10. 前缀索引
解决办法
此时可以只将字符串的一部分前缀,建立索引,这样可以大大节约索引空间,从而提高索引效率。
语法
create index idx_xxxx on table_name(columnn(n));
1
示例:
为tb_user表的email字段,建立长度为5的前缀索引
create index idx_email_5 on tb_user(email(5));
1
前缀长度 如何选择?
求选择性公式
select count(distinct email) / count(*) from tb_user; #@distinct 先除重再统计
select count(distinct substring(email, 1, 5)) / count(*) from tb_user;
12345
前缀索引 查询流程图
11. 单列索引与联合索引
是什么
在业务场景中
如果存在多个查询条件,考虑针对于查询字段建立索引时,建议建立联合索引,而非单列索引。
单列索引情况(此时phone、name都建立了索引,但不是联合索引)
explain select id, phone, name from tb_user where phone = '17799990010' and name = '韩信';
结果是只会用到phone索引字段
123
注意事项
多条件联合查询时,MySQL优化器会评估哪个字段的索引效率更高,会选择该索引完成本次查询。有时候联合索引存在,但是系统仍然自动选择单列索引查询,这时就需要自己指定索引类型了。
🕜联合索引查询 过程图