Mysql索引为什么选择B+树这种数据结构

1、二叉树无法解决单边增长的问题。

2、红黑树虽然可以通过节点旋转来达到节点自动平衡的问题、但无法有效控制树的高度。

3、B树、B+树

B树、B+树区别

相同点

每个数据页的节点都是从左到右依次递增的

不同点

  • B树数据都存储在对应的每个索引节点上且不会做冗余处理、B+树数据只存储在叶子节点上(叶子节点包含有所有的索引数据、其余非叶子节点都是冗余节点)
  • B树叶子节点的每个数据页之间没有关联、B+树叶子节点之间通过指针进行双向关联、这种关联可以大大提高范围查找的效率

Mysql中查询数据页的大小、系统默认分配的数据页的大小为16KB、不建议修改。

SHOW GLOBAL STATUS LIKE 'Innodb_page_size'

为什么系统设置的数据页的大小是16KB

因为数据页节点会被加载到内存中、如果设置过大会导致内存溢出的问题、16KB的数据页大小可以存放16 * 1024 / (8+6) = 1770

(按照索引的数据类型为Bigint占用8个字节, 地址在C语言中占用6个字节)

叶子节点因为会携带数据、暂时认为一个叶子节点的大小为1KB(正常情况下一行数据大小不会超过1KB)、一个叶子数据页可以存储16个索引

一个深度为3的B+树可以存储 1170 * 1170 * 16 = 21,902,400个索引数据、且每次查找最多只需要3次IO。

B+树的高度是由每个非叶子节点能存储多少个索引元素决定的。

什么是聚集索引/聚簇索引

  • 聚集索引/聚簇索引:叶子节点包含了完整的数据记录------Innodb(索引和数据存储在一起)
  • 非聚集索引:叶子节点只保存数据行的地址-------mylsam(索引和数据分开存储、MYD、MYI)

建表时为什么建议我们设置主键

INNODB创建表时、如果不创建主键mysql会检测其余不存在重复数据的列、利用不存在重复数据的数据列自动创建B+树、如果没有这样的列、mysql会自动创建一列隐藏列、利用该隐藏列来维护该表的B+树

为什么Mysql推荐我们使用自增长的主键

  • 很多时候hash索引要比B+树索引更高效、但时hash索引仅能满足“=”, “in”, 不支持范围查找、除此之外还会产生hash冲突
  • 因为自增的主键可以有效避免创建索引时索引元素的重新排序、B+树的重新平衡、从而提高插入数据的效率。

Mylsam的主键索引和普通索引的存储方式一样

Innodb的主键索引和普通索引的存储方式不一样

Innodb中的普通索引存储的不是行数据而是对应行聚集索引(主键)

为什么非主键索引结构叶子节点存储的是当前行的聚集索引(主键)

  • 出于索引结果一致性、如果都存储数据、当每次insert时必须得向两个索引树插入索引后才能成功、存储聚簇索引时则只需要聚簇索引树插入成功就算insert成功
  • 节省存储控空间的考虑

联合索引

1、最左前缀原理(左列原理)

使用联合索引时必须从最左边的索引开始用起、不能直接跳过最左边的直接用后面的

key `idx_name_age_position`(`name`, `age`, `position`) using btree

使用索引时不能直接跳过name用age和position

为什么时最左列原则?

因为联合索引在B+树中是按照创建联合索引中列的顺序排好序的、如果跳过最左边的列直接用后面的列索引对于整个表来说并不是按照顺序从左到右依次递增的、所以无法达到索引的目的。