索引与算法

innoDb存储引擎索引概述

支持的索引类型:

  • 1.B+树索引
  • 2.全文索引
    1. 哈希索引
  • innodb支持的hash索引是自适应的,不能人为干预,所以我们主要讨论下B+树索引
  • B+树只能找到一个数据行所在的页,然后把页督导内存,再通过页目录进行二分查找
数据结构与算法

二分查找法,对page directory进行的就是二分查找
二叉查找树和平衡二叉树

  • 二叉查找树中,左子树的键值总是小于根的键值,反之右子树值总是大于根的键值。
  • 二叉查找树问题就是容易不平衡,导致查找效率变为线性
  • 平衡二叉树:首先符合二叉查找树的定义,其次任何节点的两个子树的高度最大差1,其查找性能是较高的,最优二叉树是查找性能最高,但是插入性能最差
  • B+树是在二叉查找树和平衡二叉树中演化而来,其并不是二叉树是n阶数
B+树
  • 其是为磁盘或其他的直接存取辅助设备设计的一种平衡查找树
  • 所有的记录节点都是按照键值的大小顺序存放在同一层的叶子节点上
  • 叶子节点之间有指针类似与双向链表

B+树的插入操作

  • 插入节点需要保证叶子节点记录依然排序以及平衡
  • 一般插入的时候我们会遇到下面三种情况


    索引与算法_第1张图片
    image.png
  • 插入的逻辑是:page 会分页,一般是四个记录,当我们超过四个后就开始分页,然后把中间节点(只是类似于副本,原本的中间节点还是在叶子层,只是上层索引页也放入了中间节点的索引)放入到上一层。当上一层也满的时候也会分页
  • 但是为了尽可能减少分页,这边采用了旋转
    当叶子节点满了 但是兄弟节点没有满的情况下,既可以进行旋转
  • 所以上面的插入逻辑更改了,插入一条记录先找到对应的叶子节点如果叶子节点满了,则先去旋转左兄弟,不行再去旋转右兄弟
  • 在我看来所谓的移动就是将当前节点的首尾节点移动到旁边的页

B+树的删除操作

  • 这边有个填充因子50%是最小值(填充因子是针对叶子节点),我们可以把填充因子理解为一个页包含多少个节点,如果我们一个页为4个节点是100%,那么50%就是最少包含2个
  • 当我们删除的时候可以根据下面的原则


    索引与算法_第2张图片
    image.png
  • 删除节点的时候 如果该节点大于所在的页填充因子,则直接删除,如果对应的节点还是索引节点,则用该节点所在的叶子页的右节点去做索引节点
  • 如果小于 则需要合并,如果是如果还是索引节点 还需要更新索引节点
B+树索引
  • B+树的高度一般都在2~4层
  • 索引可以分为聚集索引和辅助索引,数据组装按照聚集索引进行查找,辅助索引按照自己的逻辑组织索引,具体如下 我们按照辅助索引搜索 先去查找k索引,然后根据k索引找到主键的索引,然后找到聚集索引进行查找记录
索引与算法_第3张图片
image.png

聚集索引

  • 就是整个表的数据就是按照b+树排列,叶子节点就是数据 ,每个叶子页都是通过双向链表来进行链接(每页之间的记录也是双链表进行维护),我们成叶子节点为数据页。
  • 非数据页的索引页存的是键值以及执行数据页的偏移量
  • 适合主键查找和范围查找
  • 聚集索引的存储物理上不连续,但是逻辑上是连续的

辅助索引

  • 辅助索引的叶子节点只包含键值(主键的),还包含了一个书签,该书签告诉innodb存储引擎可以在哪找到与索引相对于的行数据
  • 每张表可以有一个主键索引,多个辅助索引

B+树索引的分裂

  • 我们页的分裂最好不要从中间开始,这样会导致页的浪费,比如我们有1,2,3,4,5,6,7,8,9这个时候我们在插入10,则分层了p1页1,2,3,4和p2页5,6,7,8,9,10,由于插入是顺序的所以不会再有记录插入到p1导致p1 只能插入4个
  • page header 有保存插入的顺序信息,page_last_insert,page_direction,page_n_direction 这三个信息可以决定是向左还是向右进行分裂,还能决定分裂记录为哪个一个
  • 若插入是随机的,则取页的中间节点作为分裂点记录,没看懂
    索引与算法_第4张图片
    image.png

剔除了fast index creation 来创建辅助索引,不需要重建表(只需要加个s共享锁),在这之间添加或者删除索引 会创建一个新的临时表,然后把原表数据导入到临时表,删除原来表。这期间要锁全表

cardinality
  • 对于选择性比较多的适合采用b+树索引,比如1,100之间的选择就是高选择,像男女就是反例。
  • cardinality 是一个预估值。值越小代表选择性越小,1就是百分百
  • 更新cardinality值的策略就是 表中1/16的数据以及变化了
    stat_modified_counter>2000,000,00,代表某一行改变的次数大于这么多也需要更新
  • 默认对8个叶子节点进行采样,采样过程如下
B+树索引的使用
  • 联合索引
  • 多个列组成一个索引
  • 如下就是 一个记录中 ,列1值为2(主键),列2值为4找到主键为1,列2值为1,如果联合索引没有主键,那么叶子节点还是一个键值
  • 看到下面我们发现只有最左列是按照顺序排列,第二列则不是,所以按照第二列查找不会走索引


    索引与算法_第5张图片
    image.png
  • 联合索引会先按照列1进行排序,如果列1相等 就按照列2进行排序,这样一直比较到最后
    比如SELECT * FROM sakila.tb_item_param as t where a=1 orderBy b (则结果就是按照b排列的)
  • 覆盖索引
  • 指的是我们查找的值就是索引本身,不需要再去数据页查找了。
  • multi-range read
    -MRR 可以减少磁盘的随机访问,将随机访问转化为顺序的数据访问,适合范围查询(range),eq_ref(=),ref(<=>)
  • 查询辅助索引根据查询到的结果,按照主键进行排序,并按照主键排序顺序进行书签查找(比如得到了3,2,1,我们按照 1,2,3去查找)
  • 减少缓冲池中页被替换的次数
    -太多了 记不住
hash算法
  • hash表也称为散列表,是由直接寻址改进来的
  • 直接寻址表的问题,比如我们有一个值是100000,那么其按照数组的方式 采用array【1000000】去查找,假设 本身只有1,和100000,那么就要浪费剩余的空间
  • 所以上述的问题采用了hash
  • 自适应hash,当我们经常查询某个值的时候,如果没给其建立索引,则mysql会给其建立hash,个人感觉就是缓存
全文所以
  • b+树支持like '111%' ,但是不支持'%111%' ,所以采用全文检索
  • 倒排索引
  • 全文检索通过倒排索引来实现,他通过存储了单词与单词自身在一个和多个文档所在位置的之间的映射,


    索引与算法_第6张图片
    image.png
  • innodb 采用了 full inverted index 方式

你可能感兴趣的:(索引与算法)