InnoDB中索引的数据结构
起步
- 定义
索引(Index)是帮助MySQL高效获取数据的数据结构
- 本质
索引是数据结构。可以简单理解为“排好序的快速查找数据结构”,满足特定查找算法。
这些数据结构以某种方式指向数据, 这样就可以在这些数据结构的基础上实现 高级查找算法
- 优点
(1)类似大学图书馆建书目索引,提高数据检索的效率,降低数据库的IO成本,这也是创建索引最主要的原因。
(2)通过创建唯一索引,可以保证数据库表中每一行数据的唯一性。
(3)在实现数据的参考完整性方面,可以加速表和表之间的连接。换句话说,对于有依赖关系的子表和父表联合查询时,可以提高查询速度。
(4)在使用分组和排序子句进行数据查询时,可以显著 减少查询中分组和排序的时间 ,降低了CPU的消耗。
- 缺点
(1)创建索引和维护索引要耗费时间,并且随着数据量的增加,所耗费的时间也会增加。
(2)索引需要占磁盘空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,存储在磁盘上,如果有大量的索引,索引文件就可能比数据文
件更快达到最大文件尺寸。
(3)虽然索引大大提高了查询速度,同时却会降低更新表的速度。当对表中的数据进行增加、删除和修改的时候,索引也要动态地维护,这样就降低了数据的维护速度
InnoDB中索引的数据结构
- 新建表
CREATE TABLE index_demo(
c1 INT,
c2 INT,
c3 CHAR(1),
PRIMARY KEY(c1)
) ROW_FORMAT = Compact;
# 这个表使用 Compact 行格式来实际存储记录的
record_type :记录头信息的一项属性,表示记录的类型, 0 表示普通记录、 2 表示最小记录、 3 表示最大记录、 1 暂时还没用过
next_record :记录头信息的一项属性,表示下一条地址相对于本条记录的地址偏移量,我们用箭头来表明下一条记录是谁
各个列的值 :这里只记录在 index_demo 表中的三个列,分别是 c1 、 c2 和 c3
其他信息 :除了上述3种信息以外的所有信息,包括其他隐藏列的值以及记录的额外信息
-
向表中存放数据
-
B+树的演变过程
-
索引设计方案
下一个数据页中用户记录的主键值必须大于上一个页中用户记录的主键值
给所有的页建立一个目录项
- 第1次迭代
例如在上面的页10中,每页只能存放5条记录;当这1页满了后,则存放到下一页
数据存放在数据页中,每个数据页对应1个目录项
当需要查找数据时,先从目录项中根据 二分法 快速确定出主键值为 20 的记录在 目录项3 中(因为 12 < 20 <209 ),它对应的页是 页9
再去 页9 中定位具体的记录
- 目录项记录和普通的 用户记录 的不同点:
目录项记录 的 record_type 值是1,而 普通用户记录 的 record_type 值是0
目录项记录只有 主键值和页的编号 两个列,而普通的用户记录的列是用户自己定义的,可能包含 很多列 ,另外还有InnoDB自己添加的隐藏列
了解:记录头信息里还有一个叫 min_rec_mask 的属性,只有在存储 目录项记录 的页中的主键值最小的 目录项记录 的 min_rec_mask 值为 1 ,
其他别的记录的 min_rec_mask 值都是 0
- 相同点:
两者用的是一样的数据页,都会为主键值生成 Page Directory (页目录),从而在按照主键值进行查找时可以使用 二分法 来加快查询速度
- 第2次迭代
当目录项满了后,则生成第2个目录项
- 第3次迭代
为目录项生成目录项
- 第n次迭代
最后演变为B+树的数据结构
一个B+树的节点其实可以分成好多层,规定最下边的那层,也就是存放我们用户记录的那层为第 0 层,
之后依次往上加。之前我们做了一个非常极端的假设:存放用户记录的页 最多存放3条记录 ,存放目录项
记录的页 最多存放4条记录 。其实真实环境中一个页存放的记录数量是非常大的,假设所有存放用户记录
的叶子节点代表的数据页可以存放 100条用户记录 ,所有存放目录项记录的内节点代表的数据页可以存
放 1000条目录项记录
所以用到的B+树都不会超过4层