初识MySQL

服务器处理客户端请求

1. 服务器会维护线程池,为每个客户端连接分配一个线程,线程数可以动态配置

2. 解析优化

  • 查询缓存。从MySQL 5.7.20开始,不推荐使用查询缓存,并在MySQL 8.0中删除
  • 查询优化。对SQL语句做一些优化,如外连接转换为内连接、表达式简化、子查询转为连接;可以使用EXPLAIN语句来查看某个语句的执行计划

3. 存储引擎

最常用的就是InnoDB和MyISAM

字符集

1. utf8字符集表示一个字符需要使用1~4个字节,
mysql中使用的utf8是***过的utf8mb3,使用1~3个字节表示字符

2. 字符集的设置会影响char,varchar占用空间大小。因为char(10)指的是字符长度为10,而不是10字节

InnoDB记录存储结构

页是磁盘和内存之间交互的基本单位,页的大小一般为 16 KB

一次最少从磁盘中读取16KB的内容到内存中,一次最少把内存中的16KB内容刷新到磁盘中

行格式

  • Compact

默认格式

为什么变长字段和null要逆序?

变长字段长度列表

1. VARCHAR、TEXT等称为变长字段

2. 把所有变长字段的真实数据占用的字节长度都存放在记录的开头部位,各变长字段数据占用的字节数按照列的顺序逆序存放

如果该可变字段允许存储的最大字节数超过255字节并且真实存储的字节数超过127字节,则使用2个字节,否则使用1个字节

在读记录的变长字段长度列表时先查看表结构,如果某个变长字段允许存储的最大字节数大于255时,使用该字节的第一个二进制位作为标志位:如果该字节的第一个位为0,那该字节就是一个单独的字段长度,如果该字节的第一个位为1,那该字节就是半个字段长度

对于一些占用字节数大于16KB,那么如果该记录在单个页面中无法存储时,InnoDB会把一部分数据存放到溢出页中,在变长字段长度列表处只存储留在本页面中的长度,所以使用两个字节也可以存放下来。

3. 变长字段长度列表中只存储值为 非NULL 的列内容占用的长度

4. 表中所有的列都不是变长的数据类型的话,就没有变长字段长度列表 

NULL值列表

1. 将每个允许存储NULL的列对应一个二进制位,二进制位按照列的顺序逆序排列;  二进制位的值为1时,代表该列的值为NULL,二进制位的值为0时,代表该列的值不为NULL

2. 规定NULL值列表必须用整数个字节的位表示, 如果使用的二进制位个数不是整数个字节,则在字节的高位补0

3.值为NULL的列,在记录的真实数据处就不再冗余存储,从而节省存储空间

记录头信息

**


**

 固定的5个字节组成

记录的真实数据

隐藏列:每条记录都添加 transaction_id 和 roll_pointer 这两个列,但是 row_id 是可选的(在没有自定义主键以及Unique键的情况下才会添加该列)

CHAR(M)列的存储格式

1. 当列采用的是定长字符集时,该列占用的字节数不会被加到变长字段长度列表,而如果采用变长字符集时,该列占用的字节数也会被加到变长字段长度列表

2. char是固定长度的,当内容未填满时,会在其右边填充空格 

3. char固定长度,没有碎片的困扰; 但是varchar在更改前后难免会有存储碎片,因此需要定时清理碎片

4. 读取数据时,char用trim()去掉多余的空格,varchar直接读出数据

  • Redundant

MySQL5.0之前用的一种行格式,兼容旧数据

字段长度偏移列表

1. Redundant把该条记录中所有列(包括隐藏列)的长度信息都按照逆序存储到字段长度偏移列表

2. 偏移意味着两个相邻数值的差值来计算各个列值的长度

3. 直接使用整个记录的真实数据长度来决定使用1个字节还是2个字节存储列对应的偏移量

记录头信息

1byte_offs_flag:当它的值为1时,表明使用1个字节存储。 当它的值为0时,表明使用2个字节存储

相对compact,还多了n_field属性

NULL的处理

Redundant行格式并没有NULL值列表

在字段长度偏移列表中的各个列对应的偏移量的第一个比特位作为是否为NULL的依据,被称之为NULL比特位。解析一条记录的某个列时,首先看一下该列对应的偏移量的NULL比特位是不是为1,如果为1,那么该列的值就是NULL,否则不是NULL

这也就解释了为什么只要记录的真实数据大于127时,就采用2个字节来表示一个列对应的偏移量,主要是第一个比特位是NULL比特位

CHAR(M)列的存储格式

不管该列使用的字符集是啥,占用的真实数据空间就是该字符集表示一个字符最多需要的字节数和M的乘积

  • Dynamic、Compressed

这两种行格式类似于COMPACT行格式,只不过在处理行溢出数据时会在记录的真实数据处存储字符串的前768个字节,而是把所有的字节都存储到其他页面中,只在记录的真实数据处存储其他页面的地址

 另外,Compressed行格式会采用压缩算法对页面进行压缩

行溢出数据及VARCHAR(M)最多能存储的数据

1. MySQL对一条记录占用的最大存储空间是有限制的,除了BLOB或者TEXT类型的列之外,其他所有的列(不包括隐藏列和记录头信息)占用的字节长度加起来不能超过65535个字节

  1. VARCHAR(M)类型的列最多可以存储65532个字节,这样就可能造成一个页存放不了一条记录。对于Compact和Redundant行格式来说,如果某一列中的数据非常多的话,在本记录的真实数据处只会存储该列的前768个字节的数据和一个指向其他页的地址,然后把剩下的数据存放到其他页中,这个过程也叫做行溢出,存储超出768字节的那些页面也被称为溢出页

3. 什么情况下触发行溢出?MySQL规定一个页中至少存放两行记录,所以计算行最大字节数n为132 + 2×(27 + n) < 16384(132:每个页的header空间;27:每行记录的header空间;16384:一页16KB)


原文链接:https://juejin.cn/post/7061993720777801758