mysql 单表 操作 最大条数验证 以及优化

1、背景

        开车的多年老司机,是不是经常听到过,“mysql 单表最好不要超过 2000w”,“单表超过 2000w 就要考虑数据迁移了”,“你这个表数据都马上要到 2000w 了,难怪查询速度慢”。

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 '人员信息表';

  1. 插入一条数据。另外,公众 号Java精选,回复java面试,获取面试资料,支持在线刷题。
insert into person values(1,1,'user_1', NOW(), now())

利用 mysql 伪列 rownum 设置伪列起始点为 1

 
  1. select (@i:=@i+1) as rownum, person_name from person, (select @i:=100) as init;

  2. set @i=1;

运行下面的 sql,连续执行 20 次,就是 2 的 20 次方约等于 100w 的数据;执行 23 次就是 2 的 23 次方约等于 800w , 如此下去即可实现千万测试数据的插入,如果不想翻倍翻倍的增加数据,而是想少量,少量的增加,有个技巧,就是在 SQL 的后面增加 where 条件,如 id > 某一个值去控制增加的数据量即可。

 
  1. 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,这是由于你的临时表内存设置的不够大,只需要扩大一下设置参数即可。

 
  1. SET GLOBAL tmp_table_size =512*1024*1024; (512M)

  2. SET global innodb_buffer_pool_size= 1*1024*1024*1024 (1G);

先来看一组测试数据,这组数据是在 mysql8.0 的版本,并且是在我本机上,由于本机还跑着 idea , 浏览器等各种工具,所以并不是机器配置就是用于数据库配置,所以测试数据只限于参考。

ad94b4e3303d1d51610cd2355b878386.png

247a652b20c6c7223a33662d1c1b86f6.png

看到这组数据似乎好像真的和标题对应,当数据达到 2000w 以后,查询时长急剧上升;难道这就是铁律吗?

那下面我们就来看看这个建议值 2kw 是怎么来的?

3、单表数量限制

首先我们先想想数据库单表行数最大多大?

 
  1. CREATE TABLE person(

  2. id int(10) NOT NULL AUTO_INCREMENT PRIMARY KEY comment '主键',

  3. person_id tinyint not null comment '用户id',

  4. person_name VARCHAR(200) comment '用户名称',

  5. gmt_create datetime comment '创建时间',

  6. gmt_modified datetime comment '修改时间'

  7. ) comment '人员信息表';

看看上面的建表 sql,id 是主键,本身就是唯一的,也就是说主键的大小可以限制表的上限,如果主键声明 int 大小,也就是 32 位,那么支持 2^32-1 ~~21 亿;如果是 bigint,那就是 2^62-1 ?(36893488147419103232),难以想象这个的多大了,一般还没有到这个限制之前,可能数据库已经爆满了!!

有人统计过,如果建表的时候,自增字段选择无符号的 bigint , 那么自增长最大值是 18446744073709551615,按照一秒新增一条记录的速度,大约什么时候能用完?

026b11e86c2a8acc887f25ed24fe2eb2.png

4、表空间

下面我们再来看看索引的结构,对了,我们下面讲内容都是基于 Innodb 引擎的,大家都知道 Innodb 的索引内部用的是 B+ 树

334e8571e3715b41e3b01da83c79a22d.png

这张表数据,在硬盘上存储也是类似如此的,它实际是放在一个叫 person.ibd (innodb data)的文件中,也叫做表空间;虽然数据表中,他们看起来是一条连着一条,但是实际上在文件中它被分成很多小份的数据页,而且每一份都是 16K。

大概就像下面这样,当然这只是我们抽象出来的,在表空间中还有段、区、组等很多概念,但是我们需要跳出来看。面试宝典:https://www.yoodb.com

a2cca29ab37ba8d0f50001131e34ee3e.png

5、页的数据结构

因为每个页只有 16K 的大小,但是如果数据很多,那一页肯定就放不下这些数据,那数据肯定就会被分到其他的页中,所以为了把这些页关联起来,肯定就会有记录前后页地址,方便找到对应页;同时每页都是唯一的,那就会需要有一个唯一标志来标记页,就是页号;

页中会记录数据所以会存在读写操作,读写操作会存在中断或者其他异常导致数据不全等,那就会需要有校验机制,所以里面还有会校验码,而读操作最重要的就是效率问题,如果按照记录一个个进行遍历,那肯定是很费劲的,所以这里面还会为数据生成对应的页目录(Page Directory); 所以实际页的内部结构像是下面这样的。

f59a05379d352fee3ab47150dc246316.png

从图中可以看出,一个 InnoDB 数据页的存储空间大致被划分成了 7 个部分,有的部分占用的字节数是确定的,有的部分占用的字节数是不确定的。

在页的 7 个组成部分中,我们自己存储的记录会按照我们指定的行格式存储到 User Records 部分。

但是在一开始生成页的时候,其实并没有 User Records 这个部分,每当我们插入一条记录,都会从 Free Space 部分,也就是尚未使用的存储空间中申请一个记录大小的空间划分到 User Records 部分,当 Free Space 部分的空间全部被 User Records 部分替代掉之后,也就意味着这个页使用完了,如果还有新的记录插入的话,就需要去申请新的页了。这个过程的图示如下。

60dfb6b460d0b6bfa09ba49554de7840.png

刚刚上面说到了数据的新增的过程。

那下面就来说说,数据的查找过程,假如我们需要查找一条记录,我们可以把表空间中的每一页都加载到内存中,然后对记录挨个判断是不是我们想要的,在数据量小的时候,没啥问题,内存也可以撑;但是现实就是这么残酷,不会给你这个局面;为了解决这问题,mysql 中就有了索引的概念;面试宝典:https://www.yoodb.com 大家都知道索引能够加快数据的查询,那到底是怎么个回事呢?下面我就来看看。

6、索引的数据结构

在 mysql 中索引的数据结构和刚刚描述的页几乎是一模一样的,而且大小也是 16K, 但是在索引页中记录的是页 (数据页,索引页) 的最小主键 id 和页号,以及在索引页中增加了层级的信息,从 0 开始往上算,所以页与页之间就有了上下层级的概念。

e2cedc13c0420dd924389e67f0f638b7.png

看到这个图之后,是不是有点似曾相似的感觉,是不是像一棵二叉树啊,对,没错!它就是一棵树,只不过我们在这里只是简单画了三个节点,2 层结构的而已,如果数据多了,可能就会扩展到 3 层的树,这个就是我们常说的 B+ 树,最下面那一层的 page level =0, 也就是叶子节点,其余都是非叶子节点。

ae89f15f68b6d680b5c2e0acf31b47c7.png

看上图中,我们是单拿一个节点来看,首先它是一个非叶子节点(索引页),在它的内容区中有 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。

需要注意的是,图中的页号只是个示例,实际情况下并不是连续的,在磁盘中存储也不一定是顺序的。

3f94d932fe8163864ce57d7e1e65032b.png

至此,我们大概已经了解了表的数据是怎么个结构了,也大概知道查询数据是个怎么的过程了,这样我们也就能大概估算这样的结构能存放多少数据了。

从上面的图解我们知道 B+ 数的叶子节点才是存在数据的,而非叶子节点是用来存放索引数据的。

所以,同样一个 16K 的页,非叶子节点里的每条数据都指向新的页,而新的页有两种可能

  • 如果是叶子节点,那么里面就是一行行的数据

  • 如果是非叶子节点的话,那么就会继续指向新的页

假设

  • 非叶子节点内指向其他页的数量为 x

  • 叶子节点内能容纳的数据行数为 y

  • B+ 数的层数为 z

如下图中所示

Total =x^(z-1) *y 也就是说总数会等于 x 的 z-1 次方 与 Y 的乘积。

2e1905676fc2c0615881deb7854e89f7.png

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、总结

1. Mysql 的表数据是以页的形式存放的,页在磁盘中不一定是连续的。

2. 页的空间是 16K, 并不是所有的空间都是用来存放数据的,会有一些固定的信息,如,页头,页尾,页码,校验码等等。

3. 在 B+ 树中,叶子节点和非叶子节点的数据结构是一样的,区别在于,叶子节点存放的是实际的行数据,而非叶子节点存放的是主键和页号。

4. 索引结构不会影响单表最大行数,2kw 也只是推荐值,超过了这个值可能会导致 B + 树层级更高,影响查询性能。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

机器学习-基于Word2vec搜狐新闻文本分类实验

机器学习-基于Word2vec搜狐新闻文本分类实验 实验介绍 Word2vec是一群用来产生词向量的相关模型&#xff0c;由Google公司在2013年开放。Word2vec可以根据给定的语料库&#xff0c;通过优化后的训练模型快速有效地将一个词语表达成向量形式&#xff0c;为自然语言处理领域的应…

STC进阶开发(三)蜂鸣器、RTC时钟、I2C总线、外部中断、RTC闹钟设置、RTC计时器设置

前言 这一期我们首先学习如何让蜂鸣器响起来&#xff0c;并且如何让蜂鸣器发出简单的歌曲&#xff0c;然后我们介绍RTC时钟&#xff0c;要想明白RTC时钟&#xff0c;我们还需要先介绍I2C总线和外部中断。接下来就开始这一期的学习吧&#xff01; 蜂鸣器 简单介绍 蜂鸣器是一种…

论文笔记:CellSense: Human Mobility Recovery via Cellular Network Data Enhancement

1 intro 1.1 背景 1.1.1 蜂窝计费记录&#xff08;CBR&#xff09; 人类移动性在蜂窝网络上的研究近些年得到了显著关注&#xff0c;这主要是因为手机的高渗透率和收集手机数据的边际成本低蜂窝服务提供商收集蜂窝计费记录&#xff08;CBR&#xff09;用于计费目的&#xf…

哲学家进餐问题-第三十二天

目录 问题描述 解决问题 结论 问题描述 解决问题 1、 关系分析&#xff1a;找出题目中描述的各个进程&#xff0c;分析它们之间的同步、互斥关系 系统中有5个哲学家进程&#xff0c;5位哲学家与左右邻居对其中间筷子的访问是互斥关系 2、整理思路&#xff1a;根据各进程的操…

ubuntu terminator 非常好用的护眼配置

安装 sudo apt install terminator 配置文件&#xff1a;sudo gedit ~/.config/terminator/config &#xff08;如果没有就创建&#xff09; 配置如下&#xff1a; [global_config] handle_size -3 title_transmit_fg_color "#000000" title_trans…

KBDNO1.DLL文件缺失,软件或游戏无法启动运行,怎样快速修复

不少小伙伴&#xff0c;求助电脑报错“KBDNO1.DLL文件缺失&#xff0c;软件或游戏无法启动或运行”&#xff0c;应该怎么办&#xff1f; 首先&#xff0c;我们先来了解“KBDNO1.DLL文件”是什么&#xff1f; KBDNO1.DLL是Windows操作系统中的一个动态链接库文件&#xff0c;主…

Java基础进阶(学习笔记)

注&#xff1a;本篇的代码和PPT图片来源于黑马程序员&#xff0c;本篇仅为学习笔记 static static 是静态的意思&#xff0c;可以修饰成员变量&#xff0c;也可以修饰成员方法 修饰成员的特点&#xff1a; 被其修饰的成员, 被该类的所有对象所共享 多了一种调用方式, 可以通过…

MACOS Atrust服务异常

MAC版Atrust服务异常 点击进入办公后出现提示其一&#xff1a; 核心服务未启动&#xff0c;部分功能存在异常&#xff0c;确定重新启动吗&#xff1f; 可能的原因&#xff1a; 1.上次已完全退出客户端 2.核心服务被其他程序优化禁用 点击重新启动后&#xff0c;出现提示&#x…

Spring Boot 如何使用 Maven 实现多环境配置管理

Spring Boot 如何使用 Maven 实现多环境配置管理 实现多环境配置有以下几个重要原因&#xff1a; 适应不同的部署环境&#xff1a;在实际部署应用程序时&#xff0c;通常会有多个不同的部署环境&#xff0c;如开发环境、测试环境、生产环境等。每个环境可能需要不同的配置&…

虹科方案丨从困境到突破:TigoLeap方案引领数据采集与优化变革

来源&#xff1a;虹科工业智能互联 虹科方案丨从困境到突破&#xff1a;TigoLeap方案引领数据采集与优化变革 原文链接&#xff1a;https://mp.weixin.qq.com/s/H3pd5G8coBvyTwASNS_CFA 欢迎关注虹科&#xff0c;为您提供最新资讯&#xff01; 导读 在数字化工厂和智能制造时…

【新手小白的xsslab靶场学习】

第1关 最开始页面源代码 直接输入<script>alert(1)</script> 第2关 页面源代码 先尝试<script>alert(1)</script>看页面源代码 <h2>里面尖括号被编码&#xff0c;<input>里面没有编码,直接双引号闭合&#xff0c; 修改payload&…

Python 数据库(一):使用 mysql-connector-python 操作 MySQL 数据库

大家好&#xff0c;我是水滴~~ 当涉及到使用 Python 操作 MySQL 数据库时&#xff0c;mysql-connector-python 库是一个强大而常用的选择。该库提供了与 MySQL 数据库的交互功能&#xff0c;使您能够执行各种数据库操作&#xff0c;如连接数据库、执行查询和插入数据等。在本文…

Unity ShaderGraph 技能冷却转圈效果

Unity ShaderGraph 技能冷却转圈效果 前言项目场景布置代码编写ShaderGraph 连线总结 参考 前言 遇到一个需求&#xff0c;要展示技能冷却的圆形遮罩效果。 项目 场景布置 代码编写 Shader核心的就两句 // 将uv坐标系的原点移到纹理中心 float2 uv i.uv - float2(0.5, 0…

安装VS Code到AWS EC2 Linux 2

文章目录 小结问题及解决参考 小结 本文记录了安装VS Code到AWS EC2 Linux 2。 问题及解决 安装VS Code到AWS EC2 Linux 2采取了以下步骤&#xff1a; 更新VS Code的YUM源&#xff1a; [ec2-userip-100-92-28-119 ~]$ sudo rpm --import https://packages.microsoft.com/k…

Typora+PicGo+Gitee构建云存储图片

创建Gitee仓库 首先&#xff0c;打开工作台 - Gitee.com&#xff0c;自行注册一个账户 注册完后&#xff0c;新建一个仓库&#xff08;记得仓库要开源&#xff09; 然后创建完仓库后&#xff0c;鼠标移动到右上角头像位置&#xff0c;选择设置&#xff0c;并点击&#xff…

深度生成模型之GAN基础 ->(个人学习记录笔记)

文章目录 深度生成模型之GAN基础生成对抗网络1. 生成对抗网络如何生成数据2. 生成对抗原理3. GAN的核心优化目标4. D的优化5. GAN的理想状态6. GAN的训练7. 梯度不稳定与模式崩塌(collapse mode)问题8. 梯度消失问题 深度生成模型之GAN基础 生成对抗网络 1. 生成对抗网络如何…

安全数据交换系统:有效提升网间文件交换能力

各级政府部门和金融、能源、电力这些行业&#xff0c;以及一些大中型企业组织&#xff0c;为了保护内部的重要数据不外泄&#xff0c;普遍都采用了多网络并行的方式&#xff0c;也是做了网络隔离划分&#xff0c;不同的网络拥有不同的密级以及人员权限。然后再通过安全数据交换…

机器人动力学一些笔记

动力学方程中&#xff0c;Q和q的关系(Q是sita) Q其实是一个向量&#xff0c;q(Q1&#xff0c;Q2&#xff0c;Q3&#xff0c;Q4&#xff0c;Q5&#xff0c;Q6)&#xff08;假如6个关节&#xff09; https://zhuanlan.zhihu.com/p/25789930 举个浅显易懂的例子&#xff0c;你在房…

大文件断点下载Range下载zip包显示文件损坏

问题&#xff1a;大文件下载&#xff0c;其它格式的文件及rar格式的压缩包正常下载但是 之后zip包下载后解压失败 原因分析: 1. 查看上传文件的属性值 如图&#xff0c;10.4kb是已经约去小数点的值&#xff0c;准确的大小应该是10663字节10.4130859375KB&#xff0c;所以用10.…

微服务-理论(CAP,一致性协议)

CAP理论 关于CAP理论的介绍可以直接看这篇文章 CAP分别是什么&#xff1f; 一致性&#xff08;Consistency 一致性包括强一致性&#xff0c;弱一致性&#xff0c;最终一致性。 一致性其实是指数据的一致性&#xff0c;为什么数据会不一致呢&#xff1f; 如上面这张图&…