最新要闻
- 【世界新视野】抖音打不开视频怎么回事_抖音打不开
- 当前要闻:山姆同款蛋糕杭州卖165上海卖95 网友直呼太坑:你遇到过吗
- 绵云般口感!和路雪千层雪冰淇淋3.5元官方大促(商超6元)
- 今年唯一LCD性能机!Redmi Note 12T Pro外观公布-当前独家
- 重点聚焦!研究称每天排便超一次或影响健康:心力衰竭风险增加33%
- 全球快资讯丨接近小米1英寸了!曝iPhone 16 Pro Max主摄大升级
- “候鸟”老人现在是否可以在海南澄迈县买房子?深蓝苑·滨江城PK五指山森林湖养老分析!|焦点简讯
- 神舟十六号30日9时31分发射:三名航天员名单公布 首次有大学教授
- 华为畅享60X根治续航焦虑!充电宝完全派不上用场了
- 全球微资讯!华为智选车终于出轿车 奇瑞EH3谍照曝光:华为ADS摄像头瞩目
- 世界今热点:小屏4K“天花板”优派推出新款23.8英寸显示器 1999元
- 神十六乘组公布:载荷专家将首登天宫-动态
- 搜狐汽车全球快讯 | 比亚迪或考虑在法国建厂 比亚迪:正评估建厂可行性-全球资讯
- 618开车神价 爱国者4TB PCIe 4.0硬盘999元(国产长寿TLC闪存)-全球今亮点
- 特斯拉、丰田、BBA等都靠边!离开中国:世界无法生产电动车电池 当前观点
- 苹果iPhone销冠地位稳如泰山 今年618攻略请收好
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
阿里一面:MySQL 单表数据最大不要超过多少行?为什么?这样回答满分! 世界热消息
来源:https://my.oschina.net/u/4090830/blog/5559454
1 背景
作为在后端圈开车的多年老司机,是不是经常听到过,“mysql 单表最好不要超过 2000w”,“单表超过 2000w 就要考虑数据迁移了”,“你这个表数据都马上要到 2000w 了,难怪查询速度慢”
【资料图】
这些名言民语就和 “群里只讨论技术,不开车,开车速度不要超过 120 码,否则自动踢群”,只听过,没试过,哈哈。
下面我们就把车速踩到底,干到 180 码试试…….
2 实验
实验一把看看…
建一张表:
CREATE TABLE person( id int NOT NULL AUTO_INCREMENT PRIMARY KEY comment "主键", person_id tinyint not null comment "用户id", person_name VARCHAR(200) comment "用户名称", gmt_create datetime comment "创建时间", gmt_modified datetime comment "修改时间") comment "人员信息表";
插入一条数据:
insert into person values(1,1,"user_1", NOW(), now());
利用 mysql 伪列 rownum 设置伪列起始点为 1
select (@i:=@i+1) as rownum, person_name from person, (select @i:=100) as init;set @i=1;
运行下面的 sql,连续执行 20 次,就是 2 的 20 次方约等于 100w 的数据;执行 23 次就是 2 的 23 次方约等于 800w , 如此下去即可实现千万测试数据的插入,如果不想翻倍翻倍的增加数据,而是想少量,少量的增加,有个技巧,就是在 SQL 的后面增加 where 条件,如 id > 某一个值去控制增加的数据量即可。
insert into person(id, person_id, person_name, gmt_create, gmt_modified)select @i:=@i+1, left(rand()*10,10) as person_id, concat("user_",@i%2048), date_add(gmt_create,interval + @i*cast(rand()*100 as signed) SECOND), date_add(date_add(gmt_modified,interval +@i*cast(rand()*100 as signed) SECOND), interval + cast(rand()*1000000 as signed) SECOND)from person;
此处需要注意的是,也许你在执行到近 800w 或者 1000w 数据的时候,会报错:The total number of locks exceeds the lock table size,这是由于你的临时表内存设置的不够大,只需要扩大一下设置参数即可。
SET GLOBAL tmp_table_size =512*1024*1024; (512M)SET global innodb_buffer_pool_size= 1*1024*1024*1024 (1G);
先来看一组测试数据,这组数据是在 mysql8.0 的版本,并且是在我本机上,由于本机还跑着 idea , 浏览器等各种工具,所以并不是机器配置就是用于数据库配置,所以测试数据只限于参考。
看到这组数据似乎好像真的和标题对应,当数据达到 2000w 以后,查询时长急剧上升;难道这就是铁律吗?
那下面我们就来看看这个建议值 2kw 是怎么来的?
3 单表数量限制
首先我们先想想数据库单表行数最大多大?
CREATE TABLE person( id int(10) NOT NULL AUTO_INCREMENT PRIMARY KEY comment "主键", person_id tinyint not null comment "用户id", person_name VARCHAR(200) comment "用户名称", gmt_create datetime comment "创建时间", gmt_modified datetime comment "修改时间") comment "人员信息表";
看看上面的建表 sql,id 是主键,本身就是唯一的,也就是说主键的大小可以限制表的上限,如果主键声明 int 大小,也就是 32 位,那么支持 2^32-1 ~~21 亿;如果是 bigint,那就是 2^62-1 ?(36893488147419103232),难以想象这个的多大了,一般还没有到这个限制之前,可能数据库已经爆满了!!
有人统计过,如果建表的时候,自增字段选择无符号的 bigint , 那么自增长最大值是 18446744073709551615,按照一秒新增一条记录的速度,大约什么时候能用完?
4 表空间
下面我们再来看看索引的结构,对了,我们下面讲内容都是基于 Innodb 引擎的,大家都知道 Innodb 的索引内部用的是 B+ 树
这张表数据,在硬盘上存储也是类似如此的,它实际是放在一个叫 person.ibd (innodb data)的文件中,也叫做表空间;虽然数据表中,他们看起来是一条连着一条,但是实际上在文件中它被分成很多小份的数据页,而且每一份都是 16K。大概就像下面这样,当然这只是我们抽象出来的,在表空间中还有段、区、组等很多概念,但是我们需要跳出来看。
5 页的数据结构
因为每个页只有 16K 的大小,但是如果数据很多,那一页肯定就放不下这些数据,那数据肯定就会被分到其他的页中,所以为了把这些页关联起来,肯定就会有记录前后页地址,方便找到对应页;同时每页都是唯一的,那就会需要有一个唯一标志来标记页,就是页号;页中会记录数据所以会存在读写操作,读写操作会存在中断或者其他异常导致数据不全等,那就会需要有校验机制,所以里面还有会校验码,而读操作最重要的就是效率问题,如果按照记录一个个进行遍历,那肯定是很费劲的,所以这里面还会为数据生成对应的页目录(Page Directory); 所以实际页的内部结构像是下面这样的。
从图中可以看出,一个 InnoDB 数据页的存储空间大致被划分成了 7 个部分,有的部分占用的字节数是确定的,有的部分占用的字节数是不确定的。
在页的 7 个组成部分中,我们自己存储的记录会按照我们指定的行格式存储到 User Records 部分。
但是在一开始生成页的时候,其实并没有 User Records 这个部分,每当我们插入一条记录,都会从 Free Space 部分,也就是尚未使用的存储空间中申请一个记录大小的空间划分到 User Records 部分,当 Free Space 部分的空间全部被 User Records 部分替代掉之后,也就意味着这个页使用完了,如果还有新的记录插入的话,就需要去申请新的页了。这个过程的图示如下。
刚刚上面说到了数据的新增的过程。
那下面就来说说,数据的查找过程,假如我们需要查找一条记录,我们可以把表空间中的每一页都加载到内存中,然后对记录挨个判断是不是我们想要的,在数据量小的时候,没啥问题,内存也可以撑;但是现实就是这么残酷,不会给你这个局面;为了解决这问题,mysql 中就有了索引的概念;大家都知道索引能够加快数据的查询,那到底是怎么个回事呢?下面我就来看看。
6 索引的数据结构
在 mysql 中索引的数据结构和刚刚描述的页几乎是一模一样的,而且大小也是 16K, 但是在索引页中记录的是页 (数据页,索引页) 的最小主键 id 和页号,以及在索引页中增加了层级的信息,从 0 开始往上算,所以页与页之间就有了上下层级的概念。
看到这个图之后,是不是有点似曾相似的感觉,是不是像一棵二叉树啊,对,没错!它就是一棵树,只不过我们在这里只是简单画了三个节点,2 层结构的而已,如果数据多了,可能就会扩展到 3 层的树,这个就是我们常说的 B+ 树,最下面那一层的 page level =0, 也就是叶子节点,其余都是非叶子节点。
看上图中,我们是单拿一个节点来看,首先它是一个非叶子节点(索引页),在它的内容区中有 id 和 页号地址两部分,这个 id 是对应页中记录的最小记录 id 值,页号地址是指向对应页的指针;而数据页与此几乎大同小异,区别在于数据页记录的是真实的行数据而不是页地址,而且 id 的也是顺序的。
7 单表建议值
下面我们就以 3 层,2 分叉(实际中是 M 分叉)的图例来说明一下查找一个行数据的过程。
比如说我们需要查找一个 id=6 的行数据,因为在非叶子节点中存放的是页号和该页最小的 id,所以我们从顶层开始对比,首先看页号 10 中的目录,有 [id=1, 页号 = 20],[id=5, 页号 = 30], 说明左侧节点最小 id 为 1,右侧节点最小 id 是 5;6>5, 那按照二分法查找的规则,肯定就往右侧节点继续查找,找到页号 30 的节点后,发现这个节点还有子节点(非叶子节点),那就继续比对,同理,6>5&&6<7, 所以找到了页号 60,找到页号 60 之后,发现此节点为叶子节点(数据节点),于是将此页数据加载至内存进行一一对比,结果找到了 id=6 的数据行。
从上述的过程中发现,我们为了查找 id=6 的数据,总共查询了三个页,如果三个页都在磁盘中(未提前加载至内存),那么最多需要经历三次的磁盘 IO。需要注意的是,图中的页号只是个示例,实际情况下并不是连续的,在磁盘中存储也不一定是顺序的。
至此,我们大概已经了解了表的数据是怎么个结构了,也大概知道查询数据是个怎么的过程了,这样我们也就能大概估算这样的结构能存放多少数据了。
从上面的图解我们知道 B+ 数的叶子节点才是存在数据的,而非叶子节点是用来存放索引数据的。
所以,同样一个 16K 的页,非叶子节点里的每条数据都指向新的页,而新的页有两种可能
- 如果是叶子节点,那么里面就是一行行的数据
- 如果是非叶子节点的话,那么就会继续指向新的页
假设
- 非叶子节点内指向其他页的数量为 x
- 叶子节点内能容纳的数据行数为 y
- B+ 数的层数为 z
如下图中所示Total =x^(z-1) *y 也就是说总数会等于 x 的 z-1 次方 与 Y 的乘积。
X =?
在文章的开头已经介绍了页的结构,索引也也不例外,都会有 File Header (38 byte)、Page Header (56 Byte)、Infimum + Supermum(26 byte)、File Trailer(8byte), 再加上页目录,大概 1k 左右,我们就当做它就是 1K, 那整个页的大小是 16K, 剩下 15k 用于存数据,在索引页中主要记录的是主键与页号,主键我们假设是 Bigint (8 byte), 而页号也是固定的(4Byte), 那么索引页中的一条数据也就是 12byte; 所以 x=15*1024/12≈1280 行。
Y=?
叶子节点和非叶子节点的结构是一样的,同理,能放数据的空间也是 15k;但是叶子节点中存放的是真正的行数据,这个影响的因素就会多很多,比如,字段的类型,字段的数量;每行数据占用空间越大,页中所放的行数量就会越少;这边我们暂时按一条行数据 1k 来算,那一页就能存下 15 条,Y≈15。
算到这边了,是不是心里已经有谱了啊根据上述的公式,Total =x^(z-1) y,已知 x=1280,y=15假设 B+ 树是两层,那就是 Z =2, Total = (1280 ^1 )15 = 19200假设 B+ 树是三层,那就是 Z =3, Total = (1280 ^2) *15 = 24576000 (约 2.45kw)
哎呀,妈呀! 这不是正好就是文章开头说的最大行数建议值 2000w 嘛!对的,一般 B+ 数的层级最多也就是 3 层,你试想一下,如果是 4 层,除了查询的时候磁盘 IO 次数会增加,而且这个 Total 值会是多少,大概应该是 3 百多亿吧,也不太合理,所以,3 层应该是比较合理的一个值。
到这里难道就完了?
不我们刚刚在说 Y 的值时候假设的是 1K ,那比如我实际当行的数据占用空间不是 1K , 而是 5K, 那么单个数据页最多只能放下 3 条数据同样,还是按照 Z=3 的值来计算,那 Total = (1280 ^2) *3 = 4915200 (近 500w)
所以,在保持相同的层级(相似查询性能)的情况下,在行数据大小不同的情况下,其实这个最大建议值也是不同的,而且影响查询性能的还有很多其他因素,比如,数据库版本,服务器配置,sql 的编写等等,MySQL 为了提高性能,会将表的索引装载到内存中。在 InnoDB buffer size 足够的情况下,其能完成全加载进内存,查询不会有问题。但是,当单表数据库到达某个量级的上限时,导致内存无法存储其索引,使得之后的 SQL 查询会产生磁盘 IO,从而导致性能下降,所以增加硬件配置(比如把内存当磁盘使),可能会带来立竿见影的性能提升哈。
8 总结
- Mysql 的表数据是以页的形式存放的,页在磁盘中不一定是连续的。
- 页的空间是 16K, 并不是所有的空间都是用来存放数据的,会有一些固定的信息,如,页头,页尾,页码,校验码等等。
- 在 B+ 树中,叶子节点和非叶子节点的数据结构是一样的,区别在于,叶子节点存放的是实际的行数据,而非叶子节点存放的是主键和页号。
- 索引结构不会影响单表最大行数,2kw 也只是推荐值,超过了这个值可能会导致 B + 树层级更高,影响查询性能。
参考资料:
- https://www.jianshu.com/p/cf5d381ef637
- https://www.modb.pro/db/139052
- 《MYSQL 内核:INNODB 存储引擎 卷 1》
近期热文推荐:
1.1,000+ 道 Java面试题及答案整理(2022最新版)
2.劲爆!Java 协程要来了。。。
3.Spring Boot 2.x 教程,太全了!
4.别再写满屏的爆爆爆炸类了,试试装饰器模式,这才是优雅的方式!!
5.《Java开发手册(嵩山版)》最新发布,速速下载!
觉得不错,别忘了随手点赞+转发哦!
关键词:
-
阿里一面:MySQL 单表数据最大不要超过多少行?为什么?这样回答满分! 世界热消息
来源:https: my oschina net u 4090830 blog 5559454 1背景作为在后端圈开车的多年老司机,是不是经常
来源: 阿里一面:MySQL 单表数据最大不要超过多少行?为什么?这样回答满分! 世界热消息
gps网络时间服务器(时间同步装置)助力电力信息化建设|世界观焦点
deepin-for-arm64支持
全球关注:债市观察:利好钝化收益率窄幅波动 十债2.7%踌躇踏步
【世界新视野】抖音打不开视频怎么回事_抖音打不开
当前要闻:山姆同款蛋糕杭州卖165上海卖95 网友直呼太坑:你遇到过吗
绵云般口感!和路雪千层雪冰淇淋3.5元官方大促(商超6元)
今年唯一LCD性能机!Redmi Note 12T Pro外观公布-当前独家
重点聚焦!研究称每天排便超一次或影响健康:心力衰竭风险增加33%
全球快资讯丨接近小米1英寸了!曝iPhone 16 Pro Max主摄大升级
“候鸟”老人现在是否可以在海南澄迈县买房子?深蓝苑·滨江城PK五指山森林湖养老分析!|焦点简讯
JS中的arguments
今日视点:关于切片参数传递的问题
天天视点!十大券商看后市:A股底部特征浮现 市场进一步下行空间较小
神舟十六号30日9时31分发射:三名航天员名单公布 首次有大学教授
华为畅享60X根治续航焦虑!充电宝完全派不上用场了
全球微资讯!华为智选车终于出轿车 奇瑞EH3谍照曝光:华为ADS摄像头瞩目
世界今热点:小屏4K“天花板”优派推出新款23.8英寸显示器 1999元
神十六乘组公布:载荷专家将首登天宫-动态
搜狐汽车全球快讯 | 比亚迪或考虑在法国建厂 比亚迪:正评估建厂可行性-全球资讯
【独家】Linux工作原理2常用基本命令和目录层次结构
618开车神价 爱国者4TB PCIe 4.0硬盘999元(国产长寿TLC闪存)-全球今亮点
特斯拉、丰田、BBA等都靠边!离开中国:世界无法生产电动车电池 当前观点
苹果iPhone销冠地位稳如泰山 今年618攻略请收好
热消息:央视网评《家有儿女》疑似被恶意评分:小心网络评分变“粉黑大战”
山东舰穿越台湾海峡北上,台军兵推双航母“攻台”_今日热讯
【读财报】三年期互联网主题基金透视:天弘基金业绩垫底 长盛基金风格较激进
天天快消息!内存频率、容量继续狂飙 科赋宣布DDR5-8600:单条48GB
环球今亮点!史上最大屏!iPhone 16 Pro系列确认6.3/6.9英寸屏幕
LCD党福音!Redmi Note 12T Pro跑分出炉:搭载天玑8200-Ultra
每日资讯:101岁杨振宁在西湖大学致辞 给自己打分还不错 张朝阳赞其超越霍金
网络授课用什么软件好 网络授课用什么软件
【世界独家】读数据压缩入门笔记01_数据压缩导读
苹果iOS 17超前瞻 近年来最没存在感的一代?
印度官员为找手机抽掉水库210万升水!最后工作没了|当前时讯
天天热议:iPhone 15即将量产 富士康重金招人:每人3500元奖金
焦点热议:百元股上新 双元科技申购
CISCN_Dozer战队wp
环球新资讯:AutoCAD所有版本总结、序列号密钥总结大全(转载)
ZooKeeper论文阅读笔记 焦点关注
滚筒洗衣机真的比波轮的更好吗?一文读懂
死亡风险直降12%!爱发朋友圈 竟然更长寿 环球观焦点
猫咪为什么要花那么多时间梳理毛发?只是臭美吗?_速看
世界短讯!我父亲配享太庙是谁的台词
重庆长城宽带价格表_重庆长城宽带
银行汇票的付款人是谁_银行本票的有效期限为1个月 而其提示付款期限为自出票日起最长不
王老吉百家姓氏罐大促:12罐到手价29.9元
祭祀的拼音_祭祀怎么读
Oracle 死锁与慢查询总结
当前关注:天津聚力产业链优势打造信创产业基地
全球今头条!丫丫启程回京:将返回北京动物园
当前热议!Unity的Undo:详解解析与实用案例
「学习笔记」(扩展)中国剩余定理
2023-05-28:为什么Redis单线程模型效率也能那么高?|通讯
9)子查询
女模特为长高做手术“打断”腿两次:163变180 如踩高跷
网购虾条居然收到了差评返现卡:主打的就是真诚_热点
热头条丨女生一条微信状态让初中班主任找到:他像太阳一样照耀着大家
资讯推荐:猫眼端午档观众最想看的电影!《消失的她》即将上映:倪妮主演
当前热门:世乒赛战报:陈梦/王艺迪、王楚钦/樊振东夺冠,中国包揽5冠
Doris(三) -- 索引_世界快看点
梅西、迪玛利亚领衔!阿根廷国家队中国行名单公布|关注
南京玄武湖隧道内一辆宝马5系突发自燃 浓烟蔓延数百米_时快讯
哦?上一轮G7塔图姆刚刚刷新历史记录轰了51分! 天天新视野
6年了!iPhone 15无线充电迎来升级:支持Qi2标准 速讯
安卓性能最强旗舰!iQOO Neo8 Pro下周开卖:3099元起 新要闻
马云励志人生正能量八句话_马云的八句经典语录
天天关注:系统设计:从零用户扩展到百万用户
观热点:想买洗地机的用户必看:一文让你读懂洗地机
小米Civi 3上16+1TB大存储!雷军:中端机这么猛|环球简讯
《家有儿女》疑似被恶意打分:网络评分还可信吗?
“靠天吃饭”的水电如何“旱涝保收”?清洁能源助力迎峰度夏
大模型全情投入,低代码也越来越清晰
游泳时 千万不要穿白色和蓝色的泳衣 真的很危险! 世界播报
自营牧场:辉山纯牛奶7.6元/L大促 速囤-当前头条
C919飞机上有五福临门主题餐:内含上海特产大白兔牛奶
腾讯又一手游没了!《街头篮球》国服宣布7月停服
子午觉是睡眠养生之法 子午觉其中的子时和午时分别指的是-全球微速讯
世界观点:时隔6年姗姗来迟!《极限竞速》新作封面图终于公布
格局打开!波音官方庆祝C919首航成功
结转销售成本会计分录怎么写_结转销售成本会计分录
抱紧华为大腿一年 赛力斯挤进新势力前三:但还未跨过生死线|天天新要闻
世界今日报丨《西游ABC》IGN 8分:吴彦祖演技精湛 神话故事迷人
10万级大五座纯电轿车 宝骏云朵信息公开:无模组电池放心跑_全球热消息
深入分析:近端梯度下降法、交替方向乘子法、牛顿法
快看点丨30年老律师用ChatGPT旁征博引:结果被骗得禁止执业!
WinXP问世22年后 黑客发布离线激活算号器:强大程度被低估了
见证历史!国产大飞机C919首航顺利降落
西藏拉萨:藏式克朗球协会正式成立
MAC中文版 Final Cut Pro X(FCPX) V10.6.6 专属视频剪辑后期工具安装教程_全球快看
微软宣布Windows全球用户超10亿!Win11是史上最可靠操作系统 快看
特斯拉陶琳:谣言层出不穷、原因之一是流量至上
中国经济信心说丨人口高质量发展 从直面每个家庭的实际困难开始
环球微动态丨Python 标准类库-因特网数据处理之Base64数据编码
世界微资讯!2023 Sun Simiao TCM International Forum kicks off in China's Shaanxi
注意防范 7省市将现大到暴雨:部分地区有雷暴大风或冰雹-环球关注
快资讯丨直播:国产大飞机C919商业首飞!网友感叹中国人终于要坐上国产大飞机
时隔10年 索尼全新PS掌机Q公布!电池续航很堪忧
青海省内外贸易实现快速增长_新动态
一代网民青春记忆 天涯回应无法访问:拖欠多年电信IDC费已无法协商