面试题 : MySQL一棵 B+ 树能存多少条数据?
大家好,我是Tom哥~
今日寄语:充满活力的新人,能让身边的人都重回初心,真是不可思议。
mysql 的InnoDB存储引擎 一棵B+树可以存放多少行数据?
(答案在文章中!!)
要搞清楚这个问题,首先要从InnoDB索引数据结构、数据组织方式说起。
我们都知道计算机有五大组成部分:控制器,运算器,存储器,输入设备,输出设备。
其中很重要的,也跟今天这个题目有关系的是存储器。
我们知道万事万物都有自己的单元体系,若干个小单体组成一个个大的个体。就像拼乐高一样,可以自由组合。所以说,如果能熟悉最小单元,就意味着我们抓住了事物的本事,再复杂的问题也会迎刃而解。
存储器范围比较大,但是数据具体怎么存储,有自己的最小存储单元。
1、数据持久化存储磁盘里,磁盘的最小单元是扇区,一个扇区的大小是 512个字节
2、文件系统的最小单元是块,一个块的大小是 4K
3、InnoDB存储引擎,有自己的最小单元,称之为页,一个页的大小是16K
扇区、块、页这三者的存储关系?
InnoDB引擎
如果mysql部署在本地,通过命令行方式连接mysql,默认的端口 3306 ,然后输入密码即可进入
mysql -u root -p
查看InnoDB的页大小
show variables like 'innodb_page_size';
mysql数据库中,table表中的记录都是存储在页中,那么一页可以存多少行数据?假如一行数据的大小约为1K字节,那么按 16K / 1K = 16,可以计算出一页大约能存放16条数据。
mysql 的最小存储单元叫做“页”,这么多的页是如何构建一个庞大的数据组织,我们又如何知道数据存储在哪一个页中?
如果逐条遍历,性能肯定很差。为了提升查找速度,我们引入了B+树,先来看下B+树的存储结构
页除了可以存放数据(叶子节点),还可以存放健值和指针(非叶子节点),当然他们是有序的。这样的数据组织形式,我们称为索引组织表。
如:上图中 page number=3的页,该页存放键值和指向数据页的指针,这样的页由N个键值+指针组成
B+ 树是如何检索记录?
如何计算B+树的高度?
在InnoDB 的表空间文件中,约定page number = 3表示主键索引的根页
SELECT
b.name, a.name, index_id, type, a.space, a.PAGE_NO
information_schema.INNODB_SYS_INDEXES a,
information_schema.INNODB_SYS_TABLES b
WHERE
a.table_id = b.table_id AND a.space <> 0
and b.name like '%sp_job_log';
图中可以看出,每个表的主键索引的根页的page number都是3,而其他的二级索引page number为4
在根页偏移量为64的地方存放了该B+树的page level。主键索引B+树的根页在整个表空间文件中的第3个页开始,所以算出它在文件中的偏移量:16384*3 + 64 = 49152 + 64 =49216,前2个字节中。
首先,找到MySql数据库物理文件存放位置:
show global variables like "%datadir%" ;
hexdump工具,查看表空间文件指定偏移量上的数据:
hexdump -s 49216 -n 10 sp_job_log.ibd
page_level 值是 1,那么 B+树高度为 page level + 1 = 2
特别说明:
一棵树可以存放多少行数据?
假设B+树的深度为2
这棵B+树的存储总记录数 = 根节点指针数 * 单个叶子节点记录条数
那么指针数如何计算?
假设主键ID为bigint类型,长度为8字节,而指针大小在InnoDB源码中设置为6字节,这样一共14字节。
那么一个页中能存放多少这样的组合,就代表有多少指针,即 16384 / 14 = 1170。那么可以算出一棵高度为2 的B+树,能存放 1170 * 16 = 18720 条这样的数据记录。
高度为3的B+树可以存放的行数 = 1170 * 1170 * 16 = 21902400
千万级的数据存储只需要约3层B+树,查询数据时,每加载一页(page)代表一次IO。所以说,根据主键id索引查询约3次IO便可以找到目标结果。
对于一些复杂的查询,可能需要走二级索引,那么通过二级索引查找记录最多需要花费多少次IO呢?
首先,从二级索引B+树中,根据name 找到对应的主键id
然后,再根据主键id 从 聚簇索引查找到对应的记录。如上图所示,二级索引有3层,聚簇索引有3层,那么最多花费的IO次数是:3+3 = 6
聚簇索引默认是主键,如果表中没有定义主键,InnoDB 会选择一个唯一的非空索引代替。如果没有这样的索引,InnoDB 会隐式定义一个主键来作为聚簇索引。
这也是为什么InnoDB表必须有主键,并且推荐使用整型的自增主键!!!
InnoDB使用的是聚簇索引,将主键组织到一棵B+树中,而行数据就储存在叶子节点上
举例说明:
1、若使用"where id = 14"这样的条件查找记录,则按照B+树的检索算法即可查找到对应的叶节点,之后获得行数据。
2、若对Name列进行条件搜索,则需要两个步骤:
实际项目中,每个表的结构设计都不一样,占用的存储空间大小也各不相等。如何计算不同的B+树深度下,一个表可以存储的记录条数?
我们以业务日志表 sp_job_log 为例,讲解详细的计算过程:
1、查看表的状态信息
show table status like 'sp_job_log'\G
图中看到sp_job_log表的行平均大小为153个字节
2、查看表结构
desc sp_job_log;
3、计算B+树的行数
普通索引和唯一索引在查询效率上有什么不同?
唯一索引就是在普通索引上增加了约束性,也就是关键字唯一,找到了关键字就停止检索。而普通索引,可能会存在用户记录中的关键字相同的情况,根据页结构的原理,当我们读取一条记录的时候,不是单独将这条记录从磁盘中读出去,而是将这个记录所在的页全部加载到内存中进行读取。InnoDB 存储引擎的页大小为 16KB,在一个页中可能存储着上千个记录,因此在普通索引的字段上进行查找也就是在内存中多几次判断下一条记录的操作,对于 CPU 来说,这些操作所消耗的时间是可以忽略不计的。所以对一个索引字段进行检索,采用普通索引还是唯一索引在检索效率上基本上没有差别。
本文转载自微信公众号「微观技术」
原文链接:https://mp.weixin.qq.com/s/IdpY7CPxyqRNx3BYYxl2OwM
-
5道 面试题 ,拿捏String底层原理!码农参上 • 3100浏览 • 0回复
-
面试题 : MySQL 表删除 一 半 数据 , B+ 树 索引文件会不会变小?ltolll • 2597浏览 • 0回复
-
MYSQL 那点破事!索引、SQL调优、事务、 B+ 树 、分表 ....ltolll • 2398浏览 • 0回复
-
Mysql 索引- B+ 树 是如何生长的yjfhd • 2096浏览 • 0回复
-
Mysql 的索引为什么使用 B+ 树 而不使用跳表?apei_02 • 2888浏览 • 0回复
-
《吊打 面试 官》系列-Redis常见 面试题mike_hit • 2589浏览 • 0回复
-
几道高频的JVM 面试题chujichenxuyuan • 3400浏览 • 2回复
-
这个 面试题 有点意思Hunter37 • 1632浏览 • 0回复
-
你管这破玩意叫 B+ 树 ?( 一 )Hunter37 • 1541浏览 • 0回复
-
你管这破玩意叫 B+ 树 ?(二)Hunter37 • 2065浏览 • 0回复
-
某小厂 面试题 :什么是虚假唤醒?pivoteic • 1679浏览 • 0回复
-
一 些有趣的 B+ 树 优化实验(上)卡瓦格博之巅 • 1388浏览 • 0回复
-
一 些有趣的 B+ 树 优化实验(下)卡瓦格博之巅 • 1489浏览 • 0回复
-
MySQL B+ 树 索引和哈希索引介绍Only1You1 • 804浏览 • 0回复
-
一 种高性能 B+ 树 实现thire • 1901浏览 • 0回复
-
MySQL 索引底层: B+ 树 详解(修正版)我欲只争朝夕 • 1317浏览 • 0回复
-
MySQL 索引底层: B+ 树 详解我欲只争朝夕 • 683浏览 • 0回复
-
golang 面试题 :怎么避免内存逃逸?ilikevc • 1393浏览 • 0回复
-
一 文解读所有HashMap的 面试题maxdl • 244浏览 • 0回复
- 京东二面:MySQL 主从延迟,读写分离 7 种解决方案 2022-04-13 20:29:20发布
- 【故障演练】 Redis Cluster集群,当master宕机,主从切换,客户 2022-04-13 20:22:13发布