了解 MySQL的数据行、行溢出机制吗?
文章公号 首发!连载中!关注微信公号回复:“抽奖” 还可参加抽活动
在前面的文章中,白日梦曾不止一次的提及到:InnoDB从磁盘中读取数据的最小单位是数据页。
而你想得到的id = xxx的数据,就是这个数据页众多行中的一行。
这篇文章我们就一起来看一下数据行设计的多么巧妙。
一、行 有哪些格式?
你可以像下面这样看一下你的MySQL行格式设置。

其实MySQL的数据行有两种格式,一种就是图中的 Compact格式,还有一种是Redundant格式。
Compact是一种紧凑的行格式,设计的初衷就是为了让一个数据页中可以存放更多的数据行。
你品一品,让一个数据页中可以存放更多的数据行是一个多么激动人心的事,MySQL以数据页为单位从磁盘中读数据,如果能做到让一个数据页中有更多的行,那岂不是使用的空间变少了,且整体的效率直线飙升?
官网介绍:Compact能比Redundant格式节约20%的存储。
Compact从MySQL5.0引入,MySQL5.1之后,行格式默认设置成 Compact 。所以本文描述的也是Compact格式。
二、紧凑的行格式长啥样?

你肯定晓得表中有的列允许为null,有的列是变长的varchar类型。
那Compact行格式是如何组织描述这些信息的呢?如下图:

每部分包含的数据可能要比我上面标注的1、2、3还要多。
为了给大家更直观的感受和理解我只是挑了一部分展示给大家看。
三、MySQL单行能存多大体量的数据?
在MySQL的设定中,单行数据最大能存储65535byte的数据(注意是byte,而不是字符)
但是当你像下面这样创建一张数据表时却发生了错误:

MySQL不允许创建一个长度为65535byte的列,因为数据页中每一行中都有我们上图提到的隐藏列。
所以将varchar的长度降低到65532byte即可成功创建该表

注意这里的65535指的是字节,而不是字符。
所以如果你将charset换成utf8这种编码格式,那varchar(N)中的N其实指的N个字符,而不是N个byte。所以如果你像下面这样创建表就会报错。

假如encode=utf8时三个byte表示一个字符。那么65535 / 3 = 21845个字符。
四、Compact格式是如何做到紧凑的?
MySQL每次进行随机的IO读
默认情况下,数据页的大小为16KB。数据页中存储着数行。
那就意味着一个数据页中能存储越多的数据行,MySQL整体的进行的IO次数就越少?性能就越快?
Compact格式的实现思路是:当列的类型为VARCHAR、 VARBINARY、 BLOB、TEXT时,该列超过768byte的数据放到其他数据页中去。
如下图:

看到这里来龙去脉是不是很清晰了呢?
MySQL这样做,有效的防止了单个varchar列或者Text列太大导致单个数据页中存放的行记录过少而让IO飙升的窘境且占内存的。
五、什么是行溢出?
那什么是行溢出呢?
如果数据页默认大小为16KB,换算成byte: 16*1024 = 16384 byte
那你有没有发现,单页能存储的16384byte和单行最大能存储的 65535byte 差了好几倍呢?
也就是说,假如你要存储的数据行很大超过了65532byte那么你是写入不进去的。假如你要存储的单行数据小于65535byte但是大于16384byte,这时你可以成功insert,但是一个数据页又存储不了你插入的数据。这时肯定会行溢出!
其实在MySQL的设定中,发生行溢出并不是达到16384byte边缘才会发生。
对于varchar、text等类型的行。当这种列存储的长度达到几百byte时就会发生行溢。
六、行 如何溢出?
还是看这张图:

在MySQL设定中,当varchar列长度达到768byte后,会将该列的前768byte当作当作prefix存放在行中,多出来的数据溢出存放到溢出页中,然后通过一个偏移量指针将两者关联起来,这就是行溢出机制。
七、思考一个问题
不知道你有没有想过这样一个问题:
首先你肯定知道,MySQL使用的是B+Tree的聚簇索引,在这棵B+Tree中非叶子节点是只存索引不存数据,叶子节点中存储着真实的数据。同时叶子结点指向数据页。
那当单行存不下的时候,为啥不存储在两个数据页中呢?就像下图这样~。
单个节点存储下,我用多个节点存总行吧!说不定这样我的B+Tee还能变大长高(这其实是错误的想法)
这个错误的描述对应的脑图如下:

那MySQL不这样做的原因如下:
MySQL想让一个数据页中能存放更多的数据行,至少也得要存放两行数据。否则就失去了B+Tree的意义。B+Tree也退化成一个低效的链表。
你可以品一下这句蓝色的话,他说的每个数据页至少要存放两行数据的意思不是说 数据页不能只存一行。你确确实实可以只往里面写一行数据,然后去吃个饭,干点别的。一直让这个数据页中只有一行数据。
这句话的意思是,当你往这个数据页中写入一行数据时,即使它很大将达到了数据页的极限,但是通过行溢出机制。依然能保证你的下一条数据还能写入到这个数据页中。
正确的脑图如下:

参考:
https://dev.mysql.com/doc/refman/5.7/en/innodb-row-format.html
https://dev.mysql.com/doc/refman/5.7/en/column-count-limit.html
关注送书!《Netty实战》
文章公号 首发!连载中!关注微信公号回复:“抽奖” 还可参加抽活动
诚信第一,活动真实有效


了解 MySQL的数据行、行溢出机制吗?的更多相关文章
- Mysql遍历大表(Mysql大量数据读取内存溢出的解决方法)
mysql jdbc默认把select的所有结果全部取回,放到内存中,如果是要遍历很大的表,则可能把内存撑爆. 一种办法是:用limit,offset,但这样你会发现取数据的越来越慢,原因是设置了of ...
- [转]MySQL 表锁和行锁机制
本文转自:http://www.cnblogs.com/itdragon/p/8194622.html MySQL 表锁和行锁机制 行锁变表锁,是福还是坑?如果你不清楚MySQL加锁的原理,你会被它整 ...
- Mysql数据库命令行输入错误怎么办
Mysql数据库命令行输入错误 缺少另一半 错误输入 ' 或 " 时,必须键入另一半才能退出命令. 缺少分号 写入语句缺少分号需要补全. 输入quit或者exit退出 ctrl+c,完全退出 ...
- Mysql的事务及行级锁
转自:http://www.cnblogs.com/edwinchen/p/4171866.html 以签到为例,每个用户每天只能签到一次,那么怎么去判断某个用户当天是否签到呢?因为当初表设计的时候, ...
- Navicat使用教程:获取MySQL中的高级行数(第2部分)
Navicat Premium是一个可连接多种数据库的管理工具,它可以让你以单一程序同时连接到MySQL.Oracle及PostgreSQL数据库,让管理不同类型的数据库更加的方便. 在上篇文章中,我 ...
- mysql 获取刚插入行id汇总
mysql 获取刚插入行id汇总 我们在写数据库程序的时候,经常会需要获取某个表中的最大序号数, 一般情况下获取刚插入的数据的id,使用select max(id) from table 是可以的.但 ...
- 【NLP】大数据之行,始于足下:谈谈语料库知多少
大数据之行,始于足下:谈谈语料库知多少 作者:白宁超 2016年7月20日13:47:51 摘要:大数据发展的基石就是数据量的指数增加,无论是数据挖掘.文本处理.自然语言处理还是机器模型的构建,大多都 ...
- C# 设置Excel数据自适应行高、列宽的2种情况
Excel表格中,由于各种数据的复杂性,可能存在单元格中的数据字号大小.数据内容长度不一而出现,列宽过宽.过窄或者行高过大.过小的问题.常见的解决方法是调整行高.列宽.在Microsoft Excel ...
- MySQL基本操作之命令行操作
MySQL基础操作 MySQL基础操作--命令行操作
随机推荐
- [开源] .Net ORM FreeSql 1.10.0 稳步向行
写在开头 FreeSql 是 .NET 开源生态下的 ORM 轮子,转眼快两年了,说真的开源不容易(只有经历过才明白).今天带点干货和湿货给大家,先说下湿货. 认识我的人,知道 CSRedisCore ...
- Vue富文本编辑器(图片拖拽缩放)
富文本编辑器(图片拖拽缩放) 需求: 根据业务要求,需要能够上传图片,且上传的图片能在移动端中占满屏幕宽度,故需要能等比缩放上传的图片,还需要能拖拽.缩放.改变图片大小.尝试多个第三方富文本编辑器,很 ...
- JS初级运算符优先级
该图优先级由 高到低 显示
- 3号随笔,搭建web环境
创建数据库可能会遇到的问题 数据库语法错误: 如果写错了就会报错. 搭建web项目,我采用了MVC结构搭建 模型层写数据包装,controller层写业务代码,service写数据库内容,创建之后就搭 ...
- CTF-misc:老板,再来几道misc玩玩
[BJDCTF 2nd]最简单的misc-y1ng 得到一个图片,提示格式损坏,修补一下文件头 然后得到一张图片 直接python16进制转字符串 >>> string = &quo ...
- python获取当前时间、今天零点、235959点、昨天当前时间、明天的当前时间
python获取当前时间.今天零点.23:59:59点.昨天当前时间.明天的当前时间. 关注公众号"轻松学编程"了解更多. 获取当前时间.今天零点 使用timedalte. tim ...
- Nginx是什么?有什么用?
一.Nginx是什么 Nginx ("engine x") 是一个高性能的 HTTP 和反向代理服务器,特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服 ...
- 如何对List集合中的对象进行按某个属性排序
我们在实际的开发工作中,经常会碰到排序的问题,如题,我们如何针对List集合中的某一个属性进行排序 当list集合中的元素类型是我们自定义类型时,有两种对list中的元素进行排序的方法: 方法一 让l ...
- SSM实现文件上传
1.导入上传需要的jar包 commons-fileupload-1.3.3.jar commons-io-2.6.jar 2.创建 index.jsp <%@ page contentType ...
- Tomcat 总结
JavaWeb简介 JavaWeb,是用Java技术来解决相关web互联网领域的技术总和. Web包括:web服务器和web客户端两个部分,有两种软件架构 C/S:客户端/服务器端 B/S:浏 ...