Mysql索引--03---InnoDB中索引的推演

Posted 高高for 循环

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mysql索引--03---InnoDB中索引的推演相关的知识,希望对你有一定的参考价值。

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


InnoDB中索引的推演

索引之前的查找


设计索引

1. 行格式设计



我们只在示意图里展示记录的这几个部分:

  • record_type
    记录头信息的一项属性,表示记录的类型( 0 表示普通记录、2 表示最小记 录、3 表示最大记录、1表示目录项记录的record_type 值)
  • next_record
    记录头信息的一项属性,表示下一条地址相对于本条记录的地址偏移量,我们用 箭头来表明下一条记录是谁。
  • 各个列的值
    这里只记录在index_demo 表中的三个列,分别是c1 、c2 和c3 。
  • 其他信息
    除了上述3种信息以外的所有信息,包括其他隐藏列的值以及记录的额外信息。

2. 一个简单的索引设计方案

mysql 默认底层给每个节点(数据页)设置的容量大小是 16kb


3. InnoDB中的索引方案

① 迭代1次:目录项纪录的页


② 迭代2次:多个目录项纪录的页


③ 迭代3次:目录项记录页的目录页



④ B+Tree

计算一个h=3的b+树 能存多少个索引元素?

  • Mysql 默认底层给每个节点设置的容量大小是 16kb

  • 假设一个主键索引 类型为 bigint 8个字节,

  • Mysql 默认给指针分配的内存大小 是 6个字节

  • 每一个节点能存储 16*1024/(8+6)=1170个索引元素

  • 叶子节点的索引元素因为要存储data,所以按1kb的大小计算的话,一个叶子节点能存储16个索引元素

count(索引元素)=1170 * 1170 * 16=21902400

经过上述计算得知,一个高度h为3 的 B+树,叶子节点,大约能容纳2100万个索引元素.

所以上千万的数据表,MySQL也只要经过1到2次的io磁盘查找,就能获取到指定元素的数据.

常见索引概念

  • 索引按照物理实现方式,索引可以分为 2 种:聚簇(聚集)和非聚簇(非聚集)索引。我们也把非聚集 索引称为二级索引或者辅助索引。

1. 聚簇索引

B+树的叶子节点存储的是完整的用户记录



2. 二级索引(辅助索引、非聚簇索引)

所有叶子节点,非主键索引关联的是 对应主键的值

回表


3. 联合索引

  1. 先把各个记录和页按照c2列进行排序。
  2. 在记录的c2列相同的情况下,采用c3列进行排序

4.InnoDB的B+树索引的注意事项






MyISAM中的索引方案


通过索引查找数据的流程:

  1. 先通过索引文件中查找到索引节点,
  2. 从中拿到数据的文件指针,再指针定位了具体的数据。

MyISAM 与 InnoDB对比



面试题

1. 为什么不建议使用过长的字段作为主键?

因为所有辅助索引都引用主索引,过长的主索引会令辅助索引变得过大。

2. 为什么 InnoDB 上尽量采用自增字段做表的主键?

  • 因为 InnoDB 数据文件本身是一棵B+Tree,非单调的主键会造成在插入新记录时数据文件为了维持 B+Tree的特性而频繁的分裂调整,十分低效,
  • 而使用自增字段作为主键则是一个很好的选择。如果表使用自增主键,那么每次插入新的记录,记录就会顺序添加到当前索引节点的后续位置,当一页写满,就会自动开辟一个新的页

如下图所示:

  • 这样就会形成一个紧凑的索引结构,近似顺序填满。由于每次插入时也不需要移动已有数据,因此效率很高,也不会增加很多开销在维护索引上。

3.为什么推荐使用整型自增主键而不是选择UUID?

  1. UUID是字符串,比整型消耗更多的存储空间;
  2. 在B+树中进行查找时需要跟经过的节点值比较大小,整型数据的比较运算比字符串更快速;
  3. 自增的整型索引在磁盘中会连续存储,在读取一页数据时也是连续;UUID是随机产生的,读取的上下两行数据存储是分散的,不适合执行where id > 5 && id < 20的条件查询语句。
  4. 在插入或删除数据时,整型自增主键会在叶子结点的末尾建立新的叶子节点,不会破坏左侧子树的结构;UUID主键很容易出现这样的情况,B+树为了维持自身的特性,有可能会进行结构的重构,消耗更多的时间。

4. 为什么InnoDB 非主键索引结构叶子节点存储的是主键值?

  • 保证数据一致性和节省存储空间,可以这么理解:商城系统订单表会存储一个用户ID作为关联外键,而不推荐存储完整的用户信息,因为当我们用户表中的信息(真实名称、手机号、收货地址···)修改后,不需要再次维护订单表的用户数据,同时也节省了存储空间。

以上是关于Mysql索引--03---InnoDB中索引的推演的主要内容,如果未能解决你的问题,请参考以下文章

使用innodb_ruby探查Innodb索引结构

计算每天的推文

「进阶」MySQL中如何使用索引

怎么MySql添加全文索引

使用 CrossTab Pandas 获得的索引 DataFrame [重复]

mysql中,索引,主键,唯一索引,联合索引的区别是?对数据库的性能有啥影响?