为什么MySQL单表不能超过2000万行? (1)

news/2025/1/23 7:15:54/文章来源:https://www.cnblogs.com/xiaoxu0211/p/18510716


最近看到一篇《我说MySQL每张表最好不要超过2000万数据,面试官让我回去等通知》的文章,非常有趣。

文中提到,他朋友在面试的过程中说,自己的工作就是把用户操作信息存到MySQL里,因为数据量超大(5000万条左右),需要每天定时生成3张表,然后将数据取模分别存到这三张表里。

下面是两人的对话:

在这里插入图片描述

面试后续暂且不论,不过,互联网江湖上的确流传着一个说法:单表数据量超过500万行时就要进行分表分库,已经超过2000万行时MySQL的性能就会急剧下降。

那么,MySQL一张表最多能存多少数据?

今天我们就从技术层面剖析一下,MySQL单表数据不能过大的根本原因是什么?

猜想一:是索引深度吗?
很多人认为:数据量超过500万行或2000万行时,引起B+tree的高度增加,延长了索引的搜索路径,进而导致了性能下降。事实果真如此吗?

我们先理一下关系,MySQL采用了索引组织表的形式组织数据,叶子节点存储数据,非叶子节点存储主键与页面号的映射关系。若用户的主键长度是8字节时,MySQL中页面偏移占4个字节,在非叶子节点的时候实际上是8+4=12个字节,12个字节表示一个页面的映射关系。

MySQL默认是16K的页面,抛开它的配置header,大概就是15K,因此,非叶子节点的索引页面可放151024/12=1280条数据,按照每行1K计算,每个叶子节点可以存15条数据。同理,三层就是151280*1280=24576000条数据。只有数据量达到24576000条时,深度才会增加为4,所以,索引深度没有那么容易增加,详细数据可参考下表:

索引深度

最大数据量(行数)

在这里插入图片描述

搜索路径延长导致性能下降的说法,与当时的机械硬盘和内存条件不无关系。

之前机械硬盘的IOPS在100左右,而现在普遍使用的SSD的IOPS已经过万,之前的内存最大几十G,现在服务器内存最大可达到TB级。

因此,即使深度增加,以目前的硬件资源,IO也不会成为限制MySQL单表数据量的根本性因素。

那么,限制MySQL单表不能过大的根本性因素是什么?

猜想二:是SMO无法并发吗?
我们可以尝试从MySQL所采用的存储引擎InnoDB本身来探究一下。

大家知道InnoDB引擎使用的是索引组织表,它是通过索引来组织数据的,而它采用B+tree作为索引的数据结构。

B+Tree操作非原子,所以当一个线程做结构调整(SMO,Struction-Modification-Operation)时一般会涉及多个节点的改动。

SMO动作过程中,此时若有另一个线程进来可能会访问到错误的B+Tree结构,InnoDB为了解决这个问题采用了乐观锁和悲观锁的并发控制协议。

InnoDB对于叶子节点的修改操作如下:

方式一,先采用乐观锁的方式尝试进行修改
对根节点加S锁(shared lock,叫共享锁,也称读锁),依次对非叶子节点加S锁。

如果叶子节点的修改不会引起B+Tree结构变动,如分裂、合并等操作,那么只需要对叶子节点进行加X锁(exclusive lock,叫排他锁,也称为写锁)即可完成修改。如下图中所示 :

在这里插入图片描述


方式二,采用悲观锁的方式
如果对叶子结点的修改会触发SMO,那么会采用悲观锁的方式。

采用悲观锁,需要重新遍历B+Tree,对根节点加全局SX锁(SX锁是行锁),然后从根节点到叶子节点可能修改的节点加X锁。

在整个SMO过程中,根节点始终持有SX锁(SX锁表示有意向修改这个保护的范围,SX锁与SX锁、X锁冲突,与S锁不冲突),此时其他的SMO则需要等待。
在这里插入图片描述

因此,InnoDB对于简单的主键查询比较快,因为数据都存储在叶子节点中,但对于数据量大且改操作比较多的TP型业务,并发会有很严重的瓶颈问题。

在对叶子节点的修改操作中,InnoDB可以实现较好的1与1、1与2的并发,但是无法解决2的并发。因为在方式2中,根节点始终持有SX锁,必须串行执行,等待上一个SMO操作完成。这样在具有大量的SMO操作时,InnoDB的B+Tree实现就会出现很严重的性能瓶颈。

解决方案
目前业界有一个更好的方案B-Link Tree,与B+Tree相比,B-Link Tree优化了B+Tree结构调整时的锁粒度,只需要逐层加锁,无需对root节点加全局锁。因此,可以做到在SMO过程中写操作的并发执行,保持高并发下性能的稳定。

B-Link Tree主要改进点有2个:

1.中间节点增加link指针,指向右兄弟节点;

2.每个节点内增加字段high key,存储该节点中最大的key值。

新增的link指针是为了解决SMO过程中并发写的问题,在SMO过程中,B-Link Tree对修改节点逐层加锁,修改完一层即可放锁,然后去加上一层节点的锁继续修改。这样在InnoDB引擎中被SMO阻塞的写操作可以有机会在SMO操作过程中并发进行。
在这里插入图片描述

如下图所示,在节点2分裂为节点2和4的过程中,只需要在最后一步将父节点1指向新节点4时,对父节点1加锁,其他操作均无需对父节点加锁,更无需对root节点加锁,因此,大大提升了SMO过程中写操作的并发度。

由此可见,与B+Tree全局加锁对比,B-Link Tree在高并发操作下的性能是显著优于B+Tree的。GaussDB当前采用的就是B-Link Tree索引数据结构。

InnoDB的索引组织表更容易触发SMO

索引组织表的叶子节点,存储主键以及应对行的数据,InnoDB默认页面为16K,若每行数据的大小为1000字节,每个叶子节点仅能存储16行数据。

在索引组织表中,当叶子节点的扇出值过低时,SMO的触发将更加频繁,进而放大了SMO无法并发写的缺陷。

目前业界有一个堆组织表的数据组织方案,也是华为云数据库GaussDB采用的方案。它的叶子节点存储索引键以及对应的行指针(所在的页面编号及页内偏移),堆组织表叶子节点可以存更多的数据,分析可得在同样的数据量与业务并发量下,堆组织表会比索引组织表发生SMO概率低许多。

性能对比

在8U32G的两台服务器分别搭建了MySQL(B+Tree和索引组织表)与GaussDB(B-Link Tree和堆组织表)的环境,进行了如下性能验证:

实验场景:在基础表的场景上,测试增量随机插入性能。

1.基础表总大小10G,包含主键随机分布的1000w行数据,每行数据1k;

2.插入主键随机分布的1000w行数据,每行数据大小1k,测试并发插入性能。

结论:随着并发数的上升,GaussDB能稳步提升系统的TPS,而MySQL并发数的提高并不能带来TPS的显著提升。
在这里插入图片描述

综上所述,MySQL无法支持大数据量下并发修改的根本原因,是由于其索引并发控制协议的缺陷造成的,而MySQL选择索引组织表,又放大了这一缺陷。所以,开源MySQL数据库更适用于主键查询为主的简单业务场景,如互联网类应用,对于复杂的商业场景限制比较明显。

相比之下 ,采用B-Link Tree和堆组织表的GaussDB数据库在性能和场景应用方面更胜一筹。

​https://support.huaweicloud.com/intl/zh-cn/gaussdb/index.html​

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/823220.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

js逆向笔记

Cookie 和 Session: 服务器和客户端的交互仅限于请求/响应过程,结束之后便断开,在下一次请求时,服务器会认为新的客户端。 为了维护他们之间的链接,让服务器知道这是前一个用户发送的请求,必须在一个地方保存客户端的信息。 Cookie:通过在 客户端 记录的信息确定用户的身…

修改博客园主题

修改博客园主题 参考模板为:本博客皮肤 - 张贺贺呀 - 博客园 1.账号设置在账号设置中 1.选择博客皮肤为SimpleMemory,因为博客皮肤的修改是基于该皮肤 2.申请JS权限,一般申请后1-2h会通过 3.将参考模板中的代码分别粘贴到侧边栏、CSS等对应框中 2.个性化设置 完全照搬博主代…

【Java】若以框架(ruoyi-master)——10.BaseController源码了解

BaseController通用方法 Web层的通用数据。所有接口继承此方法。里面有一些各个接口会用到的通用方法。比如分页、返回消息、设置或获取一些登录信息,某些操作的时候,将日志写入或返回。方法归类 方法名称 说明请求参数预处理 initBinder() 将前台传递过来的日期格式的字符串…

GA/T1400视图库平台EasyCVR视频设备轨迹回放平台智慧园区视频监控方案

信息技术的持续进步和城市化进程的加快,使得作为城市发展关键组成部分的智慧园区对监控安全和智能管理的需求日益增长。GA/T1400视图库平台EasyCVR推出的智慧园区视频监控方案正是为了满足这一需求而设计的。该方案整合了高清视频监控、智能分析和远程管理等尖端技术,为智慧园…

百万商品查询,性能提升了10倍

前言 最近在我的知识星球中,有个小伙伴问了这样一个问题:百万商品分页查询接口,如何保证接口的性能? 这就需要对该分页查询接口做优化了。 这篇文章从9个方面跟大家一起聊聊分页查询接口优化的一些小技巧,希望对你会有所帮助。1 增加默认条件 对于分页查询接口,如果没有特…

MMpretrain使用Tiny ImageNet数据集

Tiny ImageNet是ImageNet的子集,ImageNet太大了,训练一次要好几天,于是准备用Tiny ImageNet代替ImageNet. /mmpretrain/mmpretrain/datasets/imagenet.py里面列出了ImageNet的两种格式:imagenet├── train│ ├──class_x| | ├── x1.jpg| | ├── x2.jpg| |…

在markdown上显示数学函数与数学函数图像

前言 这里分享数学函数与函数图像显示在markdown上的方式markdown编辑器 Obsidian 和 Typora数学函数显示 打开编辑器 (这里以Typora为例) 基础到可以忽略符号 html中以 & 开头, 以 ;结尾的特殊符号是可以直接输入在编辑器上显示的 图片上的显示结果即按照html源代码的格式…

如何进行颜色选择

进行颜色选择的步骤:1. 理解颜色理论;2. 考虑品牌标识和情感;3. 使用工具和资源;4. 进行A/B测试;5. 不要忽视辅助色。颜色理论是颜色选择的基础。它有助于您理解不同颜色之间的关系,以及它们如何在设计中共同协作。1. 理解颜色理论 颜色理论是颜色选择的基础。它有助于您…

C#学习 顶级语句(9)

代码与输出命名空间与类型定义 using ConsoleApp1.basic;FibonacciSequence.Run(20);MyClass.Hello(); MyNameSpace.MyClass.Hello();if (args.Length > 0) {Console.WriteLine("args的数目大于0."); } else {Console.WriteLine("args的数目为0."); }pu…

Origin2024中如何绘制雷达图?

雷达图是以从同一点开始的轴上表示的三个或更多个定量/变量的二维图表,轴径向排列显示多变量数据,也称为网络图,蜘蛛网图或星图等操作步骤: 1、先打开Origin2024软件,然后在Book1中输入如下示例数据,选中两列数据:2、点击菜单栏中【绘图】→【专业图】→【雷达图】: 3…

第10课 数据库之多表运用

一、多表查询 1、什么是多表关联查询 从2个表或者更多的表中查询我们需要的数据 2、多表连接的关系? (1)内连接 (2)左连接 (3)右连接 (4)左独有数据 (5)右独有数据 (6)全外连接 比如: a 表:1,2,3 b 表:1,2,4 内连接:显示左边12和右边12关联 …

明明花了大价钱,为什么你的CMDB还是用不起来?

明明是谁?你果然在外面有狗子了! 在IT服务管理(ITSM)的世界里,CMDB(配置管理数据库)被看作是连接各个管理流程的桥梁,它记录了IT环境中所有配置项(CI)的详细信息及其相互关系。然而,在实践中,许多组织尽管投入了大量资源来构建和维护CMDB,却发现CMDB难以有效使用。…