Mysql中b树索引hash索引的特点、使用场景、使用限制、以及索引的优化策略【转载】

索引


索引:告诉存储引擎如何快速的找到表中的数据,当表中的数据少查询少,索引的性能可能显示不出来,因为这个时候表中的数据基本上可以缓存到内存中,就算是进行全表扫描也不会太慢,随着表中的数据越来越多,查询频率也越来越多,内存已经不能完全缓存数据的时候,索引的功能就显示出来了

实际工作中,总是忽略或者过分的强调索引,太多或者太少都会带来不好的影响
mysql支持的索引类型,mysql的索引就是告诉存储引擎如何快速的找到表中的数据,因此索引是在存储引擎层来实现的,而不是在mysql的服务器层实现的,这就决定了不同的存储引擎用的索引类型是不同的,同时不是所有的存储引擎都会支持所有的类型,即使是同一种类型的索引,在不同的存储引擎上在底层的实现上也可能不太相同
B-tree索引是最常见的索引,通常说的索引指的就是B树索引,使用的是B+树的结构来存储数据,在B+树种每一个叶子节点都包含一个指向下一个节点的叶子指针,可以方便的进行叶子节点之间的遍历

B树索引的特点


首先,B树索引是以B+树的结构来存储数据的
B树索引能够加快存储引擎的查找速度,通常情况下,索引的大小远远小于表中数据的大小,使用了B树索引之后就不用再进行全表扫描而是从索引的跟节点开始搜索索引的根节点种存放了指向下一个节点的指针
存储引擎根据这些指针向下一场进行查找,通过比较节点中的值,就能得到合适的节点,这些指针中定义了子节点中的上限和下限,最终存储引擎能够找到节点中的值是不存在的,找到符合要求的叶子节点,叶子节点指向的是被索引的数据,而不是其他的叶子节点
B树索引是顺序存储的,适合进行范围查找

什么时候使用b树索引


全值匹配的时候就是和索引中的所有列进行匹配,比如在 oorder_sn建立了B树索引,则oorder_sn=‘9595456232’
匹配最左前缀的查询,比如如果在order_sn上面没有建立索引,而是建立了,而是在order_sn和order_data两个列建立一个联合索引,只要这个索引的第一列符合查询条件,这个索引就会用到,如果只是这个联合索引的第二列符合这个条件,比如查找order_data,这样的查找条件是无法利用B树索引的
匹配列前缀的查询,匹配列前缀和匹配最左前缀是不同的,比如 order_sn like '9876%'开头的订单号,这个查询可以利用order_sn列的联合索引,也可以利用order_sn和order_data的联合索引
进行范围查找的时候可以利用到B树索引,order_sn>‘989890809’ and order_sn<‘fadsfadsfa’
精确匹配最左前列并范围匹配另外一列,就是说匹配order_sn第一列,order_data是一个范围
只访问索引的查询,就是说查询只要访问索引而不需要访问数据行,这种查询的效率高。
B树索引除了使用在查询 过滤语句中还可以使用在orderby语句中,因为B树索引是按照顺序来存储的

B树索引的限制


B树索引有什么限制,明明建立了索引,但是查询的时候却无法使用的索引这种情况,这和很多因素有关,比如,如果使用索引命中的数据如果占用了表中的大部分的数据,那么,mysql的查询优化器可能会认为使用全表扫描的方式会更好,就不会使用索引的方式进行查询,使用B树索引有很多限制,如果是在B树索引使用在受限制的地方就无法使用到索引,使用B树索引的限制有什么?
如果不是按照从索引的最左列开始查找的,则无法使用索引
使用B树索引的时候,不能跳过索引中左边的列而使用索引,这里指的是左边的列而不是最左边的列
通常来说not in 和<>操作是无法使用索引的
如果查询中有某个列是范围查询,则其右边所有列都无法使用索引

hash索引


memory存储引擎使用的支持hash和B树,innodb也支持hash索引,innodb的hash索引不是我们建立的而是通过索引的使用情况自己建立的,因此innodb的hash索引又称为自适应hash索引
hash索引的特点,首先hash索引是 基于hash表来实现的,查询条件只有精确匹配的时候才能够使用hash索引,hash索引用于等值查询中,如果要进行范围查询或者模糊查询就不能使用hahs索引
hash索引,索引中的所有列,存储引擎都会为每一行计算一个hash码,hash码都是比较小的,并且不同键值行的hash码通常是不一样的,hash索引中存储的就是Hash码,这就是为什么hash索引只能进行全职匹配的查询,因为只有这样,hash码才能够匹配,同时在hash索引表中保存了hash码代表的每一行的数据指针,因为hash索引中只有每一行的hash码,索引数据结构紧凑,使得使用hash索引找到数据的速度很快,但是也存在一些限制


hash索引的限制


使用hash索引查找数据必须进行两次读取,因为hash索引中包括的只是键值,hash码和执行对应行的指针,索引中没有保存对应的值,索引首先必须要找到对应的行,之后对对应的行的值进行读取,如果使用hash索引进行查询要进行两次查找,但是memory存储引擎和innodb存储引擎的被频繁访问的行基本上都是缓存在内存中,对内存中的数据进行访问速度都很快,
其次hash索引是按照hash码的顺序来存储的而不是按照键值的方式来存储的,不能像B树索引一样对查询结果进行排序
hash索引只能进行全键值的匹配查找,而不支持部分键值的匹配查找,同时也不支持键值的范围查找,这也是hash索引的存储特点决定的,无法把一个范围值和具体的hash码进行匹配
hahs索引在进行hash索引的时候会出现hahs冲突,hash索引不适合用在选择性差的列上面,重复值很多的列上,身份证的列比较好,因为重复的少
hash 索引和B树索引是最常见的两种类型,索引的优化也是针对这两种类型进行的

为什么要使用索引,索引是不是越多越好


快速定位数据,大大减少存储引擎要扫描的而数据量
另外b树索引的键值是按照顺序来存储的,因此可以利用索引进行排序,避免使用临时表进行排序的io消耗 索引可以把随机I/O转变为顺序I/O


索引是不是越多越好?


索引会增加写操作的成本,在进行数据的更新操作或者删除操作的时候,必须要对相关的索引或者统计信息进行维护,所以,索引越多,修改数据所需要的时间就越长,为了解决这个问题,innodb引入了插入缓存,将多次插入操作合并为一次插入操作,innodb只要要有一个自增的io主键
过多的索引也会影响数据库的查询的性能,mysql的查询优化器会根据索引的信息和查询的条件来为其选择合适的索引,如果对同一个查询有很多的索引可以使用,则会增加mysql查询优化器对查询进行分析的时间,只有在适当的列上创建适当的索引,才是真正合适的
在每一列上都建立索引,当where条件后面的列很多的情况下mysql也不一定会全部的使用,在5.0版本之前每个查询只能使用一个列上索引,对于where条件过多的这种列如果存在过多的查询条件,并不能使用到每一列上的索引,mysql5.0之后因为了合并

为什么要对索引进行优化

正确的创建和使用索引是实现数据库高性能查询的基础,如何进行使用?

b树索引的使用策略:

  1. 如果某一个列是索引列,则该列不能使用表达式或函数

对大字符串建立索引,支持对字符串前缀建立索引

msyql中的B树索引对于键值的大小是有限制的,限制和使用的存储引擎的不同而不同,对于innodb存储引擎而言,索引键的的最大大小不能超过767个字节约为utf-8下的255个字符,而myisam索引列的宽度是1000个字节超过了宽度是无法创建索引,这对大字符串可能不够,为了能够对大字符串比如text类型建立索引 ,另一方面索引很长的字符串列也会对索引的使用变得很慢,达不到索引优化的目的,因此mysql支持对字符串的前缀建立索引,可以大大减少索引的空间,提高索引的查询效## 标题率
**对大字符串建立索引,支持对字符串的前缀建立索引,**通过
create index index_name on table(col_name(n));这方式创建索引要指定列得宽度,对于innodb来说索引列的的宽度不能超过767个字节约为utf-8下的255个字符,而myisam索引列的宽度是1000个字节超过了宽度是无法创建索引。虽然可以在大字符列上使用前缀索引增加了大字符串得查询效率,但是前缀索引也降低了索引得选择性,索引的选择性指的是不重复得索引键值和表的记录数得比值,在选择前缀索引的使用既要保证索引要尽可能的小也要保证索引的选择性不能太差

联合索引


对于单列上的索引来说,在查询上建立多个列的查询可能是一个更好的查询优化方法,是按照索引列的顺序来存放的,索引的先后顺序也决定了查询是否可以使用到这个索引

如何选择联合索引中索引列的顺序?

经常被用到的列优先,非常频繁的使用某一个列进行过滤,则这个列放在联合索引的最左边,如果是选择性很差的列也不适合放在联合索引的最左边
选择性高的列优先使用,如果mysql的选择性很高,则进行最左边的过滤之后,剩余的内容就没有多少了,之后再进行过滤就快很多
宽度小的列优先使用,表示使用索引的io越小
覆盖索引:
覆盖索引:

可以优化缓存,减少磁盘IO操作,
减少随机IO,将随机IO转变为顺序IO
可以避免对Innodb主键索引的二次查询
可以避免MyISAM表进行系统调用,无法使用覆盖索引的情况,存储引擎不支持覆盖索引
查询中含有太多的列
使用了双%号的like查询

版权声明:本文为CSDN博主「一只小猛子」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_41174684/article/details/90372212

发布了4 篇原创文章 · 获赞 0 · 访问量 190

猜你喜欢

转载自blog.csdn.net/cyb_17302190874/article/details/105573811