文章目录
- 1. 索引匹配原则
- 2. 一般建议
- 3. 问题1 `=和in可以乱序`
- 4. 问题2 复合索引的选取
1. 索引匹配原则
- 全值匹配我最爱
- .最佳左前缀法则
- 不在索引列上做任何操作(计算、函数、(自动or手动)类型转换,会导致索引失效而转向全表扫描
- 存储引擎不能使用索引中范围条件右边的列
- 尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致)),减少select
- mysql 在使用不等于(!= 或者<>)的时候无法使用索引会导致全表扫描
- is not null 也无法使用索引,但是is null是可以使用索引的
- like以通配符开头(‘%abc…’) mysql索引失效会变成全表扫描的操作, "xxx%"有可能使用使用,也不一定百分百使用索引
- 字符串不加单引号索引失效
- 少用or,用它来连接时会索引失效
2. 一般建议
- 对于单键索引,尽量择针对当前query过滤性更好的索引
- 在择组合索引的时候,当前Query中过滤性最好的字段在索引字段顺序中,位置越靠前越好。(避免索引过滤性好的索引失效),在择组合索引的时候,尽量择可以能够包含当前query中的where字句中更多字段的索引,尽可能通过分析统计信息和调整query的写法来达到择合适索引的目的
3. 问题1 =和in可以乱序
如果 建立索引a_b_c 那么 select * from b=2and a=1会走索引吗? 会
建索引的几大原则
- 最左前缀匹配原则,非常重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配
比如a = 1 and b = 2 and c > 3 and d = 4 - 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,
- 如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。
=和in可以乱序
比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式。
4. 问题2 复合索引的选取
假设有这样一个表,里面有500w数据,假设创建了两个索引,一个是idx_de_no(deleted, task_no),另外一个是idx_no(task_no),当查询条件是 where delete=0 and task_no=‘xxx’ 时,会走哪个索引?
-- auto-generated definition
create table test_index
(
id int unsigned auto_increment comment '主键'
primary key,
task_no varchar(256) not null comment '任务编号',
task_name varchar(256) null comment '质检任务名称',
remark varchar(1000) null comment '说明',
creator varchar(30) null comment '创建人',
updater varchar(30) null comment '更新人',
create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',
update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
deleted tinyint(1) default 0 not null comment '0:正常 1:删除'
)
comment '测试';
create index idx_de_no
on test_index (deleted, task_no);
create index idx_no
on test_index (task_no);
答案是:会走 idx_no(task_no) 索引,而不是走idx_de_no(deleted, task_no),原因是索引查询优化器还会根据统计信息、表的大小和复杂度等因素来决定最终使用的索引,delete字段只有0和1两种可能,复杂度太低,优化器最终会选择idx_no索引进行查询,所以我们在选取字段做复合索引时,会优先使用复杂度高的(零散度高的)字段;