mysqlb树字符串索引_Mysql从⼊门到⼊神之(四)B+树索引前⾔
⽂本已收录⾄我的GitHub仓库,欢迎Star:github/bin39232820…
种⼀棵树最好的时间是⼗年前,其次是现在
我知道很多⼈不玩qq了,但是怀旧⼀下,欢迎加⼊六脉神剑Java菜鸟学习,聊号码:549684836 ⿎励⼤家在技术的路上写博客
spacex公司絮叨
我们继续来探索mysql。前⾯我们了解了mysql的索引的⼀些基础知识,今天我们来康康B+树索引
来复习⼀下⼀下昨天的 ⾸先是InnoDB的页存储结构,我们知道 多个不同的页组成的是⼀个双向链表,⽽每个页⾥⾯的数据⾏会按主键的⼤⼩组成⼀个单向链表,并且每4到8个数据组成⼀个槽,每个槽存储在pageDirectoy⾥⾯ ,当我们要查询页的⾏数据的时候,可以先定位到页,然后⽤2分法定位到槽,然后遍历槽,来定位到当前⾏的数据。(⼤佬画的图,⼤家可以好好理解⼀下)
其中页a、页b、页c ... 页n 这些页可以不在物理结构上相连,只要通过双向链表相关联即可。
没有索引下的查数据的⽅式
第⼀种,查询的是id主键的⼀个确定值,这个好像还不是那么难,⾸先遍历所有的页,定位到页,从页⾥⾯到槽,从槽⾥⾯到当前⾏,所以这样说的话,这种如果页数⽐较多的话,查询也会很慢
第⼆种,也就是我们说的全表扫描,⼀个个去遍历,最后来到这⼀⾏数据,因为这种查询的会⾮常的慢,所以呢我们的索引就派上⽤场了
InnoDB中的索引⽅案
InnoDB是使⽤页来作为管理存储空间的基本单位,也就是最多能保证16KB的连续存储空间,⽽随着表中记录数量的增多,需要⾮常⼤的连续的存储空间才能把所有的⽬录项都放下,这对记录数量⾮常多的表是不现实的。
我们时常会对记录进⾏增删,假设我们把页中的记录都删除了,页也就没有存在的必要了,那意味着⽬录项也就没有存在的必要了,这就需要把⽬录项后的⽬录项都向前移动⼀下,这种牵⼀发⽽动全⾝的设计不是什么好主意~
它是怎么来实现 ,页记录 和⽤户⽤户记录 ,它每个⾏数据中⼜⼀个record_type 这个既可以表⽰,页记录 和⽤户⽤户记。它有以下的4种取值⽅式
0:普通的⽤户记录
1:⽬录项记录
2:最⼩记录
3:最⼤记录
不论是存放⽤户记录的数据页,还是存放⽬录项记录的数据页,我们都把它们存放到B+树这个数据结构中了,所以我们也称这些数据页为节点。从图中可以看出来,我们的实际⽤户记录其实都存放在B+树的最底层的节点上,这些节点也被称为叶⼦节点或叶节点,其余⽤来存放⽬录项的节点称为⾮叶⼦节点或者内节点,其中B+树最上边的那个节点也称为根节点。
聚簇索引
上⾯的B+数 本⾝就是⼀个主键索引 我们也叫聚簇索引,它有两个特点
使⽤记录主键值的⼤⼩进⾏记录和页的排序,这包括三个⽅⾯的含义:
存放⽬录项记录的页分为不同的层次,在同⼀层次中的页也是根据页中⽬录项记录的主键⼤⼩顺序排成⼀个双向链表。 (树的每⼀层都是⼀个双向链表)
各个存放⽤户记录的页也是根据页中⽤户记录的主键⼤⼩顺序排成⼀个双向链表。(最后⼀层的⽤户数据层也是⼀个双向链表)
页内的记录是按照主键的⼤⼩顺序排成⼀个单向链表。(页内是⼀个单休链表,和⼀个有着顺序的槽⽬录)
B+树的叶⼦节点存储的是完整的⽤户记录。所谓完整的⽤户记录,就是指这个记录中存储了所有列的值(包括隐藏列)。
我们把具有这两种特性的B+树称为聚簇索引,所有完整的⽤户记录都存放在这个聚簇索引的叶⼦节点处。这种聚簇索引并不需要我们在MySQL语句中显式的使⽤INDEX语句去创建(后边会介绍索引相关的语句),InnoDB存储引擎会⾃动的为我们创建聚簇索引。另外有趣的⼀点是,在InnoDB存储引擎中,聚簇索引就是数据的存储⽅式(所有的⽤户记录都存储在了叶⼦节点),也就是所谓的索引即数据,数据即索引。
⼆级索引
⼤家有⽊有发现,上边介绍的聚簇索引只能在搜索条件是主键值时才能发挥作⽤,因为B+树中的数据都是按照主键进⾏排序的。那如果我们想以别的列作为搜索条件该咋办呢?难道只能从头到尾沿着链表依次遍历记录么?
不,我们可以多建⼏棵B+树,不同的B+树中的数据采⽤不同的排序规则。⽐⽅说我们⽤c2列的⼤⼩作为数据页、页中记录的排序规则,再
建⼀棵B+树,效果如下图所⽰:
其实这个呢,和上⾯的也差不都就是说这个说⼦节点存放的是我们的索引列+我们的主键的数据。如果我们想要当前那⼀⾏的所有数据的话,我们是需要做⼀次回表操作的。
设计网页的公司联合索引
我们也可以同时以多个列的⼤⼩作为排序规则,也就是同时为多个列建⽴索引,⽐⽅说我们想让B+树按照c2和c3列的⼤⼩进⾏排序,这个包含两层含义:
先把各个记录和页按照c2列进⾏排序。
在记录的c2列相同的情况下,采⽤c3列进⾏排序
类似于这种,就是先把第⼀个列做好索引,然后再排第⼆个列,必须按先后顺序来,所以我们所说的前缀索引就是这样来的。
索引的代价
在熟悉了B+树索引原理之后,本篇⽂章的主题是唠叨如何更好的使⽤索引,虽然索引是个好东西,可不能乱建,在介绍如何更好的使⽤索引之前先要了解⼀下使⽤这玩意⼉的代价,它在空间和时间上都会拖后腿:
空间上的代价
这个是显⽽易见的,每建⽴⼀个索引都要为它建⽴⼀棵B+树,每⼀棵B+树的每⼀个节点都是⼀个数据页,⼀个页默认会占⽤16KB的存储空间,⼀棵很⼤的B+树由许多数据页组成,那可是很⼤的⼀⽚存储空间呢。
时间上的代价
每次对表中的数据进⾏增、删、改操作时,都需要去修改各个B+树索引。⽽且我们讲过,B+树每层节点都是按照索引列的值从⼩到⼤的顺序排序⽽组成了双向链表。不论是叶⼦节点中的记录,还是内节点中的记录(也就是不论是⽤户记录还是⽬录项记录)都是按照索引列的值从⼩到⼤的顺序⽽形成了⼀个
单向链表。⽽增、删、改操作可能会对节点和记录的排序造成破坏,所以存储引擎需要额外的时间进⾏⼀些记录移位,页⾯分裂、页⾯回收啥的操作来维护好节点和记录的排序。如果我们建了许多索引,每个索引对应的B+树都要进⾏相关的维护操作,这还能不给性能拖后腿么?
创建⾼性能索引原则
独⽴的列
select from语句什么意思呢?就是我们where = 后⾯的条件,必须是独⽴的⼀个列,不能是id+1,这种计算,所以有⼀个原则就是始终将索引列单独放在⽐较符合的⼀侧。
mysql菜鸟教程字符串型前缀索引
⽐如⼀个字符串很长,然后你要给这个字段建⽴索引,如果说他们前⼏个字段的识别度很⾼了话,就建议建⽴⼀个前缀索引。这样就可以⼤⼤的节省索引空间
多列索引
类风湿挂什么科
⼀个常见的错误就是,给每个列都建⽴⼀个索引,这样是错误的,还有就是建⽴联合索引的时候的顺序是随便填的,这种⽅式也是错误的。如果你⽤explain 关键字看到了 索引合并的信息,就说明你这个索引看是否能否优化。
选择合适的索引顺序
假设你有2个列要建⽴组合索引,那么这个组合索引的列的字段到底是哪个先 哪个后呢?这个是没有⼀定的标准的,但是默认的条件是如果你有数量少的字段尽量是放到前⾯,在不考虑,分组的条件下,这种情况确实是⽐较快的。
覆盖索引
覆盖索引的意思就是我们建⽴索引的时候,我把需要查询的条件⼀起建⽴⼀个联合索引,那么查询这些数据的时候,我们就不需要回表操作了。
尽量⽤索引扫描来排序
如果explain中type的结果是index,就说明mysql使⽤了索引扫描来做排序,
未使⽤的索引
如果发现有些索引是⼀直不会使⽤的索引,建议删除它。
不可以使⽤索引进⾏排序的⼏种情况
ASC、DESC混⽤
对于使⽤联合索引进⾏排序的场景,我们要求各个排序列的排序顺序是⼀致的,也就是要么各个列都是ASC规则排序,要么都是DESC规则排序。
WHERE⼦句中出现⾮排序使⽤到的索引列
总结
索引并不是想建就建,凡事都是有代价的吗,我们只能说权衡利弊
索引通⽤的⼀些场景
等值查询
匹配组合索引左边的索引
匹配组合索引的左边的索引的范围查询
匹配等值查询和范围查询
分组查询
排序
索引的⼀些注意事项
只为搜索,分组,排序的列建⽴索引
只为数据的识别度⾼的列建⽴索引(例如性别就不建议建⽴索引)
对于字符串的列,如果它的能建⽴前缀索引,最好就建⽴前缀索引
为了让页尽量减少页分裂的情况,最好给主键建⽴⾃增
删除不必要的索引
如果能⽤覆盖索引的尽量⽤覆盖索引,减少回表的次数。
结尾
⽇常求赞
sublime安装教程
好了各位,以上就是这篇⽂章的全部内容了,能看到这⾥的⼈呀,都是真粉。创作不易,各位的⽀持和认可,就是我创作的最⼤动⼒,我们下篇⽂章见
六脉神剑 | ⽂ 【原创】如果本篇博客有任何错误,请批评指教,不胜感激 !

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。