youngwang12138 / blog-gitalk

0 stars 0 forks source link

mysql数据页和索引页 #8

Open youngwang12138 opened 2 years ago

youngwang12138 commented 2 years ago

https://zhongyang.wang/post/1660050910/

前言 每个表中的数据被分成页。构成每个表的页面排列在称为B+树索引的树数据结构中。表数据和二级索引都使用这种类型的结构。页又可以分为数据页和索引页,是MySQL数据存储的最小单元,默认为16kb。B+树中的一个叶子节点是一页 结构图 其中上半部分为索引页,下半部分为数据页 数据页 数据行 数据页是磁盘中的一段数据,那么里面记录的就是数据行。数据行是一个单向链表结构,由前一行指向下一行 页目录 如果数据页里的行数少,那么可以直接遍历。当数据越来越多时,直接遍历就很慢了,那就需要给这些行创建目录—页目录。 如果页目录如果给每行记录都加一个目录项,那就没有意义了。这里使用稀疏索引,每个目录项记录第一行数据的id。先在页目录中通过二分查找确定目录项,再遍历目录项指向的单向链表遍历数据。MySQL会自动的维护页目录 那么问题来了,如果数据一个数据页放不下,在数据遍历的时候怎么办呢?数据页双向链表的结构优化这个问题。(对应于聚簇索引里叶子节点的双向链表便于遍历) 索引页 当数据页很多的时候,如何确定去哪页查找数据呢?这就是索引页的作用。 类似于页目录的方式,对每一个数据页提取最小id和页地址信息,通过二分查找的方式确定数据页地址。当数据页很多的时候,随着二叉树高度的增加,查找效率就下降了,有没有更好的方式呢? 要加快树的查找效率,那就压缩树的高度。把原本每个非叶子节点只存一个数据的形式,改成可以存放16个,树的高度大大降低。 如果记录按顺序插入,索引页的填充因子为15/16,否则是1/2~15/16(随机插入时,会发生频繁的也分裂合并操作,性能很低;且也会数据会变得稀疏不规则,会存在数据碎片)。 以上数据页加上索引页就形成了聚簇索引。 一颗聚簇索引可以覆盖多少数据呢 主键索引非叶子节点存放主键值和指针,地址和主键大小按照文档分别为5字节和6字节;每条数据按照500字节算,每个数据页大概可以存放161024/500=32条数据。 当树高为1时,root节点为叶子节点,直接存数据161024/500=32 当树高为2时,可索引的数据页为161024/11=1490,数据量为146032=47680 当树高为3时,数据量为1460149032=71043200,在达到这个数据量前,基本就需要考虑分表了。 缓冲池全部为B+树时可以多少数据呢 缓冲池的默认大小为128M,可以通过参数innodb_buffer_pool_size配置,比如10G。假如128M全部加载B+树,数据量为1281024/1632=262144

youngwang12138 commented 1 year ago

冲啊