MySQL优化(二.索引的介绍)

索引的介绍

索引的作用

1.提高查询的速度
2.提高排序的速度
3.提高分组的速度

bTree类型的索引

内部实际采用二叉树的数据结构,例如

              4
	2           6
     1    3      5     7

采用类似的数据结构将数据的查询时间复杂度从N/2降低到log2N



hash类型的索引

采用hash算法,将每一个主键进行自定义的hash函数从而直接得到数据存储的地址,因为是直接进行运算得到的地址,不需要进行查找,所以查询时间复杂度为(

优点
快(适用于精准查询)

缺点

1.因为是随机放置数据,所以容易引起内存空洞
2.因为是对某一个主键进行hash函数的运算,可能在精准查询的时候很快,但是碰到范围查询时不能进行优化,例如where id>20
3.无法使用前缀索引(具体定义见下文),而bTree可是使用前缀索引
4.排序无法优化
5.必须进行回行,即hash只能得到地址,所以需要进一步根据地址去取值(bTree的聚簇索引不需要)



索引左前缀

建立一个多列索引 a,b,c

语句 是否发挥作用
where a = 1 a 发挥作用
where a= 1 and b = 2 a,b发挥作用
where a= 1 and b = 2 and c = 3 a,b,c发挥作用
where b = 1 / where c= 1
where a= 1 and c = 1 a发挥作用
where a= 1 and b > 10 and c = 1 a,b发挥作用
where a= 1 and b like “123%” a,b发挥作用
where a= 1 and b like “%123” a发挥作用

因为多列索引具有顺序性和左前缀性
例如 a,b,c是一根完整的管道,当没有b时只有a能用,c是断的所以不能用
当只有b,c或者只有b只有c时,因为坐前缀性,因为左边没有a所以整根管道处于断路,都不能用
当b为"123%“时,因为左边为确认值,所以b能部分使用,但是处于b后面的都不能用
当b为”%123"时,因为左边为不确认值,所以b不能使用,所以b以及处于b后面的都不能用

经典索引题
现有a,b,c,d四列,将a,b,c三列建立索引

语句 是否发挥作用 备注
where a =1 and b = 1 and d >8 and c = 1 a b c都能起作用 虽然语义上不符左前缀,但是mysql会自动优化
where a =1 and b = 1 and d >8 order by c a b c都能起作用 ab作用于查询,c用于排序
where a =1 and d >8 order by c,b a都能起作用 a作用于查询,bc虽然建立索引但是顺序不符合左前缀
where a =1 and d >8 order by b,c a,b,c都能起作用 a作用于查询,bc用于排序
where a =1 and b = 2 order by b,c a,b,c都能起作用 a,b作用于查询,c用于排序



二级索引

一般为多列的索引,其无论主键索引是聚簇索引还是非聚簇索引,其存放的数据仅为指向主键的位置的指针,即指向主键

索引覆盖

当查询的内容就是索引的一部分时,就不会产生回行现象,查找速度较快
例如 表test建立了a,b的联合索引
select a from test where a = 1 and b = 3;(快)
select c from test where a = 1 and b = 3;(慢)


聚簇索引(innerDb)

虽然采用二叉树的数据结构,但是叶子不仅保存数据的地址还保存实际数据

                                    4[索引|实际数据] 
	        2[索引|实际数据]                        6[索引|实际数据] 
     1[索引|实际数据]      3[索引|实际数据]      5[索引|实际数据]      7[索引|实际数据]  

优点
1.查询速度较快

因为索引与数据存放在一起,所以不存在回行现象,所以查询速度较快

2.排序速度较快

因为索引与数据存放在一起,所以不存在回行现象,所以可以避免fielsort操作,排序速度较快

2.当乱序插入数据的时候,结果依然有序(非聚簇索引不一定)

当聚簇索引插入数据,当生成索引树的时候,因为聚簇索引索引与数据存放在一起,因为索引是根据二叉树有序的,所以数据也是有序的,而非聚簇索引,因为索引树只存放相关实际数据的地址,所以乱序存放时并不会自动排序



缺点
当插入顺序不规律时,会形成页分裂现象,速度会比非聚簇索引稍慢

因为叶子存储索引与所有的数据,所以叶子较重,当插入顺序不规律时,因为要生成二叉树时,因为叶子较重,速度会比较慢(使用固态硬盘会有所缓解)

经典样例
例如一个innerdb的表test,定义了,a,b,c三列,其中c为text的超长列,a为主键,再定义a,b为一个索引
select * from test order by a;(很慢)
select * from test order by a ,b;(很快)

关键原因如下
1.存储引擎为innerdb(使用聚簇索引),如果使用非聚簇索引则查询速度一致
2.使用的索引为主键索引,因为有大数据列存在所以,主键索引树较重所以速度较慢
3.有大数据列c存在,如果没有大数据列,查询速度相差不大

虽然a建立了主键索引,但是因为是聚簇索引,所以主键a会与大数据c一起放在一棵索引树内,会非常重,而二级索引a,b则是另一个索引树,存放数据仅为主键的地址,所以查询速度会比主键还快,所以建议合理建立索引,合理使用索引



非聚簇索引(myisam)

虽然采用二叉树的数据结构,但是叶子不仅保存数据的地址还保存实际数据
内部实际采用二叉树的数据结构,例如

                         4[索引]
	        2[索引]             6[索引] 
     1[索引]      3[索引]      5[索引]      7[索引]  



利用索引进行排序

一.排序的数据是索引的一部分
发生索引覆盖,速度很快

二.排序的数据与是索引无关
这个时候mysql会将数据取出形成一个临时表,然后进行filesort(可能会在磁盘上进行)

在非聚簇索引中,虽然可以根据有序的索引去一边取索引一边取数据,这样取出的数据虽然也是有序的.
但是因为频繁的回行效率很低,所以非聚簇索引的数据库引擎会先把所有的数据取出然后对数据直接进行排序,
因为可能会在磁盘上进行,所以速度可想而知,我们应该尽可能的去避免filesort

我们需要争取去数据库取出的数据就是有序的(利用索引进行排序)

当sql语句的查询操作使用的索引与排序操作的索引不一致时,虽然两个操作都使用了索引,但是还是会产生filesort,
例,test表有cat_id与good_id这两个单列索引
select * from test where cat_id > 10 order by good_id;(使用filesort)
select * from test where good_id > 10 order by good_id;(未使用filesort)

因为当查询操作使用的索引与排序操作的索引不一致时,根据where查询出来的语句对order使用的索引依然是无序的,所以还是会产生filesort

猜你喜欢

转载自blog.csdn.net/qq_38052995/article/details/82985443