本文主要是做笔记用的,所以有些凌乱,不喜勿喷。
tabA 表的组合索引 a,b,c a varchar(24) 非空, b int(11) 非空 , c varchar(20) 非空
下面sql执行计划的索引长度 key_len=140 , 计算方法: 设计表的时候会有一段字符编码,一般设置为utf-8,占3个字节,gbk 占2个字节,拉丁 占1个字节 (24+20)*3(utf-8 是每个长度由3个字节来存储) +intlength(4)+0(标志位,允许为空的额外长度计算值)+4(varchar类型最终要加2个字节,2个varchar4个字节)=140
下面sql执行计划的索引长度 key_len=78 , 计算方法: 设计表的时候会有一段字符编码,一般设置为utf-8,占3个字节,gbk 占2个字节,拉丁 占1个字节 24*3(utf-8 是每个长度由3个字节来存储) +int(4)+2(varchar类型最终要加2个字节 )=78
1)模糊查询 like ,失效情况 like后面直接加通配符
1)普通索引或者组合索引第一列用的范围查询,效率也很高,【因为会用到索引,innodb 的b+tree底层叶子会指向相邻叶子地址,是个双向链表,且叶子节点存储有序。】
explain select * from tabA where a>'tom'2)组合索引用到了范围查询 这里索引长度key_len=78,说明索引只用到了 a,b ; c没有用到,说明组合索引用范围查询时,范围查询列后面的索引列会失效。
explain select * from tabA where a='tom' and b>1 and c='cat'3)只用索引列做查询
explain select a,b,c from tabA where a='tom' and b=1 and c='cat'执行计划extra = using index 表示索引覆盖,无需回表,效率高。
1 、or生效情况 tabB表,只有 a,b,c 三个字段,均为int 类型且允许为null ,且为联合索引 a,b,c
explain select * from tabB where a=1 or b=3 ;适用了联合索引,且key_len=15 ,= 4(int 长度为4)*3(3个int)+3(3个允许为空,每个空占一个字符)。表示索引用到了 a,b,c
explain select * from tabB where a=1 ; -- 执行计划里 key_len=5使用and
explain select * from tabB where a=1 and c=4 ; -- 执行计划里 key_len=5; explain select * from tabB where a=1 and b=4 ; -- 执行计划里 key_len=10;2 or失效情况 tabC表,4个字段 a,b,c,d,且联合索引为 a,b,c a,b,c均为int类型,d为varchar(10) 类型,均允许为空。
-- 索引失效,执行计划里,没有使用索引。 explain select * from tabC where a=1 or b=3 ; -- 索引失效 。 explain select * from tabC where a=1 or a=3 ; explain select * from tabC where a in(1,3) ;如果不查询普通列,则用or也不会使索引失效,且key_len=15
explain select a,b,c from tabC where a=1 or b=3 ;小结:列全部是组合索引,即便使用or,索引也会生效。 表里除了组合索引的列,还含有其他列, 全表扫描的时候, 组合索引 a用in和or都会失效, a=1 and b>2 and c=1 b后面的c会失效,因为用到了范围查询
索引失效情况: 1 order by a asc, b desc 2 like ‘%ms’ 通配符在前面的,大多数情况会导致索引失效,但不绝对 3 组合索引 a,b,c a=1 and b>2 and c=1, c会失效,因为b用到了范围查询 4 索引列上有函数 5 不满足最左前缀 6 使用不等号 7 隐士类型转换。比如varchar类型,结果写成数字,数据库会自动做类型转换,这个索引字段的索引功能就会失效
1 、tabD ,a主键,b 索引,组合索引(c,d)
EXTRA using index explain select c,d from tabD\G2、tabE a主键,b 索引,c 普通列。
EXTRA using index explain select a,b from tabE where b='123'\G EXTRA:null explain select a,c from tabE where b='123'\G比如 a*3=15 这种,可以改为a=15/3 ,或者拿到业务层计算,不要在数据库层面去计算。
a. 索引的选择性越高,查询效率越高,唯一索引的选择性是1,是最好的索引,性能也是最好的。 b. 索引的选择性:率重后的索引值和总记录数的比值 c. 对于很长的varchar类型的列,或者blob,text的列,必须使用前缀索引,mysql不允许索引这些列的完整长度。 d:前缀索引缺点:不能group by,order by ,和索引覆盖扫描
索引存储的时候就维护数据按顺序存储。
-- 执行计划key=rental_date extra:using index conditions explain select rental_id ,staff_id from rental where rental_date='2005-05-31' order by inventory_id,customer_id\G --去掉invetory_id 的时候,key:rental_date ,extra: using index conditions,using filesort【表示用到文件排序】 explain select rental_id ,staff_id from rental where rental_date='2005-05-31' order by customer_id\G -- 去掉where条件,索引会失效,加上下面这个where条件,索引生效 explain select rental_id ,staff_id from rental where rental_date='2005-05-31' order by rental_date,inventory_id,customer_id\G --- 执行计划key=null extra:using where ;using filesort 联合索引范围查询,索引失效 explain select rental_id ,staff_id from rental where rental_date>'2005-05-31' order by rental_date,inventory_id \G -- 排序一升一降 ,索引失效 explain select rental_id ,staff_id from rental where rental_date='2005-05-31' order by inventory_id desc ,customer_id asc \G如果是单列索引,通常情况下,or会使用索引; 如果是组合索引: a 全部列均为组合索引,会用对应的索引, b如果部分列是组合索引,那么不会使用索引。 具体是否生效,还是要看实际情况来分析。
比如varchar类型,没加单引号,那么执行的时候,会导致该索引列失效。
基数,率重/总数 超过80% ,可以创建索引。
limit起到一个限制输出的作用,分页查询只是他的一个附带功能。但是涉及到limit 1000000,5 这种偏移量比较大的,可以替换为使用 in 或者 between and ,或者子查询 或者先投影查询再内联查。
索引过多也会给数据库造成压力,影响性能。