MySQL 索引篇

文章目录

    • MySQL 索引篇
      • B+树索引的选择
      • 索引结构总结
      • 索引分类
        • 聚簇索引与非聚簇索引
      • 回表 索引覆盖 最左匹配
      • 索引失效
      • 索引下推

MySQL 索引篇

前提知识:

  • 磁盘预读: 内存在和磁盘进行交互时,有一个最基本单位称之为页(datapage),大小一般是4k或8k,在进行数据的读取时,一般读取的是页的整数倍 – mysql innodb存储引擎默认预读大小为16k

为什么需要索引?

  1. 数据库实际数据存储在硬盘中;当进行查询时,需要将磁盘中的数据读取到内存中,分块进行数据读取(读取页的整数倍)
  2. 使用索引可以减少io次数以及减少io量,从而加快查询速度

B+树索引的选择

索引底层数据结构是 B+树 – 数据存储格式(Key - Value)

对于数据存储格式key-value,可能会首先想到hash表作为索引 – hash索引

在进行等值查询时会很高效,但对于范围查询、模糊查询、排序等情况都不适用,且还需要考虑hash冲突带来的影响。

为什么不是二叉树、二叉搜索树BST、红黑树

  1. 以上树有一个共同之处 – 节点最多含有两个子节点

  2. 当数据量越来越大时,需要通过加深树的深度去存储更多的数据,树的深度越深,树的层次越多,导致io次数变多,进而影响查询数据的效率

如果使用多叉排序树 – B树

  1. 使用B树作为索引结构:

    每个磁盘块(页的整数倍)中:包含每个索引键值以及对应的数据data

  2. 假设每个磁盘块大小为16k,数据data为1k,那么每个磁盘块最多存储16条记录,那么三层的B树最多能存储16x16x16=4096条记录,那么对比现实大数据量而言是远远不够的

  3. 同样我们可以通过加深树的深度去存储更多的数据,让B树为4层、5层…,那么同样伴随的是:树的深度越深,树的层次越多,导致io次数变多,进而影响查询数据的效率

不能变深,我们可以选择变胖,刚刚磁盘块中主要占据空间的是data数据

B+树的特点:

  1. B树的扩展 --同样是多叉排序树
  2. 叶子节点含有其他层次节点数据的冗余,且从水平层次上看,叶子节点有指针指向,可以看成是一个链表

B+树作为索引数据结构 与B树相比的改进

  1. 除却数据结构本身结构的改变 – 变胖
  2. 每个非叶子节点磁盘块只存储数据
  3. 那么同样都是3层的B+树,假设非叶子节点中每个索引值+指针占据10字节,叶子节点data数据同样按1k进行计算,B+树可存储(16*1024/10)的二次方 x 16 ~= 40960000

一般情况下3-4层的B+树索引足以支撑千万级的数据,具体能存储的数据量还需看索引所占据的空间大小,因而索引key值要尽可能少的占用空间。

索引结构总结

  1. hash索引:
    • hash索引底层原理基于哈希表,因此在进行等值查询时会很高效,但对于范围查询、模糊查询、排序等情况都不适用,且还需要考虑hash冲突带来的影响
  2. b树索引和b+树索引:
    • 从结构上看,b树的叶子节点是相互独立的,b+树的叶子节点是有指针指向的,那么在进行范围查询的时候b+树可以通过叶子结点的循环遍历得到结果,而b树不支持这样的操作
    • 从节点存储的内容上看,b树的节点同时存储键和值,如果所查询的数据在距离根节点近的位置,那么对于查询非常高效,但这具有随机性的;b+树除了叶子节点都只存储键,那么对于随机检索,都必须走一条从根节点到叶子结点的路径,相比b树会更稳定。也正因为节点存储内容不同,b树所能存储的数据量小于b+树,b+树所能蕴含的信息是数万级的。当然具体的数据情况要看索引的大小。

索引分类

  1. 主键索引 – 索引:主键字段
  2. 唯一索引 – 唯一字段
  3. 普通索引 – 非主键非唯一
  4. 全文索引 – 全文检索 – 效率极低 – 一般不在数据库中使用
  5. 联合索引 – 表中的多个字段共同构成索引

索引越多越好嘛?

并不是;每个索引都是一棵B+树,索引的维护会非常麻烦,索引文件占用存储空间变大,因而需根据业务情况建立合适的索引

聚簇索引与非聚簇索引

  1. 聚簇索引是以主键为索引值建立,叶子节点中存储的是该主键对应的整条数据记录
  2. 非聚簇索引的不同之处在于叶子节点存储的是该索引对应的记录的主键

除了聚簇索引,其他索引的叶子节点存储的是索引和对应的主键值;不同索引虽然是不同的B+树,但该表的数据只会存储一份

在innodb存储引擎中,聚簇索引的索引列选择:

  1. 该表声明主键,则主键为索引列;
  2. 没有声明主键,但含有唯一字段,该字段为索引列
  3. 没有唯一字段,则会使用存储引擎生成的隐字段 – 6字节rowid作为索引列

存储引擎 – 不同的数据文件在磁盘的不同组织形式;

innodb含有非聚簇索引也含有聚簇索引

myisam含有非聚簇索引,不含有聚簇索引;因而数据文件和索引文件是分开放的

聚簇索引严格意义上说并不是一种索引类型,而是一个索引归类,即索引可以分为聚簇索引和非聚簇索引。

回表 索引覆盖 最左匹配

  • 回表:查询的内容包含除索引、主键外的字段时,在根据索引值得到主键值,再根据主键读取数据记录,这种查询方式叫做回表

  • 索引覆盖:当我们所查询即select的列字段包含在索引中,那么就不需要通过回表去查询数据即可返回结果。

  • 最左前缀匹配原则:当我们所查询的限制的字段在联合索引的最左端时,如name,age这两个为索引,那么当我们对name或者name,age进行限制时都可以通过该索引进行查询

通过explain + sql语句 查看是否走了索引

索引失效

  1. 当mysql认为全表扫描会比走索引更有效率时
  2. 对索引字段操作时,如where a+1 = 1时;b为字符串,where b = 1,mysql数据转化都是将字符串转换为数值0,索引失效
  3. 当查询的字段不符合当前索引的最左前缀匹配原则时,索引失效
  4. 模糊查询时 以%开头索引失效,or语句当钟包含不是索引信息部分
  5. 使用 not 、<>、!=等操作时,使用全表扫描不使用索引

索引下推

  • 在使用非聚簇索引进行查询时,通过索引检索到数据,然后返回给MySQL服务器,服务器判断数据是否符合条件
  • 在使用索引下推的情况下,如果存在某些索引列的判断条件时,可以由存储引擎判断该索引列是否符合条件,只有当索引符合条件时才会将数据检索出来返回
  • 索引条件下推优化可以减少存储引擎查询基础表的次数,也可以减少MySQL服务器从存储引擎接收数据的次数

以name 和 age建立索引 ,查询 name like “陈%” and age = 20时,如果没有索引下推那么会先判断名字为name的记录,假设当前有两条(只有一条age = 20),那么就需要通过主键值进行两次回表,通过回表的数据判断一次age = 20的记录。使用索引下推,就会将age = 20的条件也判断了,那么只需回表一次。
有效减少回表的次数

你可能感兴趣的:(MySQL,mysql,b+树)