一、建立索引的原则
1、表的主外键必须有索引
2、经常与其他表进行连接的字段应该建索引
3、数据量大的表应该建立索引
4、经常出现在where条件中的字段
5、经常出现在order by、group by distinct后面的字段,索引的顺序和关键字后面的顺序一致
6、对于查询做很少涉及的列,重复值比较多的列不建议建索引
7、对于定义为text、image和bit的数据类型不建议建索引
8、对于经常修改的列不建议建索引
9、复合索引,按照最左匹配的原则只有复合索引的第一个字段出现在查询条件里才走索引
假设数据库中有a、b、c三个字段建立复合索引(顺序abc)等价于建立a、ab、ac、三个索引,
那么按照最左匹配原则
select * from table where b = '2' and c= '3';不走索引(数据库不知道怎么下手)
select * from table where a = '1' b = '2' and c= '3';走索引(数据库索引先比较a然后再确定下一步)
select * from table where b = '2' a = '1' and c= '3';走索引(数据库帮我们优化了顺序)
在最左匹配原则中,有如下说明
mysql向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and
c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,只用到了复合索引a,b,c列。d是用不到索引的,如果建立(a,b,d,c)的索引则都可以
用到,a,b,d的顺序可以任意调整。
=和in可以乱序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会
帮你优化成索引可以识别的形式
10、单表索引不要超过4个
11、索引尽量建在值为not null的字段中
12、频繁增删改的字段不建议建立索引
二、索引失效场景
1、索引的字段参与计算(+-*/)
select * from table where age+1=10;
2、索引的字段使用了函数
select * from table where to_char(create_time,'yyyymmdd')='19901002';
3、使用like
select * from table where name like '%张三%';
select * from table where name like '%张三';
select * from table where name like '张三%';按照最左匹配原则是可以的
4、隐式转换
select * from table where name status = 1
如果数据表中status字段是varchar类型,那么就存在因式转换,导致索引失效
5、取反操作
not in、not exist 、!=、 <>
6、in和or
查询优化器分析走索引比较慢会走全表扫(离散性太差)
关于索引知识点
主键索引(聚簇索引):主键索引的叶子节点存的是一条完整的记录
唯一索引:列值唯一的字段上建立的索引
回表:普通索引只存主键索引的值和子节点引用,所以要查询一条完整的记录必须通过
普通索引的值先定位到主键值,再定位到该行记录,这个操作称为回表操作
索引下推:
对索引中包含的字段先做判断,过滤掉不符合条件的记录,减少回表字数。
建立复合索引(name,age)
SELECT * from t_user where name like '张三%' and age = 20;
在5.6版本之前数据库引擎会忽略age这个字段,直接通过name进行查询,在(name,age)这课树上查找到了两个结果,id分别为2,1,然后拿着id值一次次的回表查询,因此这个过程需要回表两次。
在5.6版本之后数据库引擎并不会忽略age这个字段,而是在索引内部就判断了age是否等于20,对于不等于20的记录直接跳过,因此在(name,age)这棵索引树中只匹配到了一个记录,此时拿着这个id去主键索引树中回表查询全部数据,这个过程只需要回表一次