1、索引的本质是排好序的快速查找的数据结构。表查询多,增删改少,就加索引。、
(一个字段不同记录数/总记录数,越高,建索引意义越大)
2、为什么删数据一般都是软删,status从0到-1:
1)为了保留数据记录,供数据查询分析
2)为了不破坏索引,否则会降低索引命中率,降低查询效率
3、索引分类:
1)单值索引:一个索引只包含一个列,一个表可以多个单值索引,但不建议超过五个,值可以不唯一
2)唯一索引:索引列的值必须唯一,但允许有空值
3)复合索引:一个索引包含多个列
4、索引结构:
1)Btree索引(java开发最常用,最需要关注)
2)Hash索引
3)full-text全文索引
4)R-tree索引
5、EXPLAIN(执行计划):
1)id:表示查询语句中,查询表的语句的执行顺序
a)id相同时,顺序从上到下
b)id不同时,id值越大,越先执行,NULL最小最后
2)select_type:表示查询的类型,主要用于区别 普通查询,联合查询,子查询等的复杂查询
a)SIMPLE:简单的select查询,不包含任何子查询或UNION
b)PRIMARY:若存在子查询,则最外层,最后查的那个表就是
c)SUBQUERY:在SELECT中或WHERE中的子查询语句的表
d)DERIVED:临时表
e)UNION:SELECT UNION语句,UNION之后的表被标记会UNION
f)UNION RESULT:UNION后的结果集表
3)type(访问类型):(除了index对select和where都有要求,其余的都只对where有要求,type展示的是语句中使用到的最高级的type,也就是部分查询用到了,并不是语句中所有查询都符合。所以经常能出现,明明type级别高到range甚至ref,后面还存在Using where提示 )
system > const > eq_ref > ref > range > index > ALL
system:select from 只有一行的表,一般为系统表
const:select * from table where id = 2,用primary key或unique,只匹配一行数据
eq_ref:select * from employee t1,department t2 where t1.deptId = t2.id,用t2的primary key或unique作为t1表的外键,t1的每个记录在t2表中只会有一条匹配
ref:select * from table where name = "张三" 用普通index查询,匹配到多条数据
range: between,<,>,in, like 的范围查询,在普通index上查询
index:select id from table where id ***,只需要扫描索引(包括primary key,unique,index)列就够返回了,且where后面的条件也只针对索引列,就算index。有多个索引的时候,也一样,只要select的所有列在任意的索引里,就是Index。
ALL:select * from table 全表扫描,从硬盘中读取
4)possible_keys(一个查询语句可能用到的索引,但并不一定是真的用到的索引):
5)key(最终实际使用的索引)
6)key_len(该列计算查询所使用的索引长度,越短越好,是通过创表时的表列的长度计算得出,并不是实际使用长度):
7)ref:显示索引的哪一列被使用了,甚至到哪一个常量(type为const和eq_ref和ref语句就是)被使用了
8)rows:每张表里,要能走完where后的所有条件,一共需要用到哪些行,这写行数
举个例子:select * from table where a = 1 and b = 2;
table表中,一共100条数据,a有index索引,b没有索引,a = 1有20行,a=1且b=2有5行,
那么这个语句,a有索引等于20次常量匹配,一共检索了20行,and后面的语句都是在这20行里筛选,所以最后的rows为20
9)Extra:
a)Using filesort:排序列没有索引,急需优化
b)Using temporary:需要创建临时表来查询,急需优化,一般为group by无索引列
c)Using index:查询的列,都在索引包含列里,无需读取实际行信息。
d)Using where:where后的过滤条件字段,存在无法用索引的情况
6、常见索引失效原因:
1)全局匹配all,缺索引
2)索引没从最左列开始(全部失效),或者中间列断了(部分失效)
3)在索引列上用函数,(自动or手动)类型转换(where bigint类型列 = “”)
4)范围查询右边的所有查询条件都不会使用索引了
5)减少使用select *,尽量只返回索引覆盖列
6)使用 != 或者 <> 会导致索引失效
7)使用is null 或者is not null 会导致索引失效
8)like虽然type是range,但只有"%","_" 放右边的时候才是range,%只放右边(a%aa%也算,只要常量开头的,都算放右边了)的时候,虽然是范围的,但不会断索引,复合索引后面的字段照样可以继续用到索引。%放左边,索引直接失效,不说后面的不能用索引,连自身都没算用了索引。
(在必须要%放前面的情况,怎么优化索引?只能使用index了,为了使where name like "%aa%",
就必须建立一个以name为最左匹配的复合索引,把其余需要返回的列也包含进去。
如 select name,age from table where name like "%aa" 可以建复合索引name_age)
9)复合索引,用and按从左匹配,是可以用用到索引的,但是用了or,索引就失效了
7、常见误区:
1)复合索引c1_c2_c3,虽然中间断了就只能部分使用了,但mysql会做自动转换,只要索引的所有列都在where里and了,就会自动排序。即where c2 = 1 and c3 = 2 and c1 = 3,也是ref。但是最好还是推荐按顺序写,这个字段转换顺序也是耗时耗性能的。
2)已经确定是常量,只有一份的时候,order by就可以无视了
如:where c1 = 1 and c2 = 2 order by c2,c3 等同于 where c1=1 and c2 = 2 order by c3
where c1 = 1 and c2 = 2 order by c3,c2 等同于 where c1=1 and c2 = 2 order by c3
例子中,因为c2已经是常量,索引是c1_c2_c3,即便order by c3,c2 也不会出现Using filesort
8、order by
1)where和order by一起合起来,排组合索引的顺序
2)复合索引的多列,必须都是同一种排序方向才行,否则直接using filesort
9、group by实质上,是先排序后分组的,所以索引基本规则和order by一样
10、看到第49