1. 它起什么作用?
它是一种将数据存储在磁盘上的表中的存储引擎。
2.如何读写数据?
处理数据的过程发生在内存中,需要将磁盘中的数据加载到内存中,如果是处理写或者修改请求,则需要将内存中的内容刷新到磁盘。
磁盘的读写速度非常慢,比内存的读写速度慢几个数量级。因此,当我们想从表中获取一些记录时,存储引擎会将数据分成若干个页面,以“页面”作为磁盘与内存交互的基本单位,一个页面的默认大小为 16 KB。也就是说,一般情况下,每次至少会从磁盘读取 16KB 的内容到内存中,或者每次至少会将内存中的 16KB 内容刷新到磁盘中。
所以当你测试一个分页查询接口的时候,发现第一次打印需要300~400ms,后续查找下一页需要30~40ms。原因是第一次请求接口的时候,读数据库的时候需要读磁盘,需要把16KB的数据从磁盘加载到内存中。下一页的数据都是从内存中获取的,不需要再读磁盘。除非16KB内存中的数据找不到了,才会再次读磁盘获取下一个16KB数据放入内存中。(.0放弃的查询缓存特性就不讨论了,我测试过.7关闭查询缓存,第一次还是慢,但是后续查询就快了,查询时间差大概10倍)
❝
温馨提示:分页查询和数据库一个16KB的页里的“页”是两个不同的概念。
❞
注意:该变量在服务器运行时无法更改,只能在首次初始化 MySQL 数据目录时指定。因此,页面大小在运行时无法更改。
另外MySQL系列面试题及答案全部整理出来,大家可以微信搜索Java面试库,在线阅读。
3. 很多问题 - 行格式
❝
看到这里,你肯定和我一样有疑问,比如(255)后面的最大长度该怎么取?为什么不可以是(65535),而最大只能是(16383)?我来给你演示一下!
❞
我们通常以“记录”为单位将数据插入表中。这些“磁盘上的记录存储方式”也称为行格式或记录格式。行格式有四种类型:
MySQL 5+ 的默认行格式为 ,MySQL 5 和 MySQL 8 中也证实如此。
SHOW VARIABLES LIKE "innodb_default_row_format"
在业务和日常使用中你几乎没修改过或者关注过行格式,所以“我将只关注默认的行格式”,以便你在日常开发中有更深入的了解。
请记住这个表结构,我们后面会讲到
CREATE TABLE test (
c1 VARCHAR(10),
c2 VARCHAR(10) NOT NULL,
c3 CHAR(10),
c4 VARCHAR(10)) CHARSET = utf8mb4;
现在业务数据库字符集都这样了,我就用这个来讲解,尽量减少理解难度。
INSERT INTO test ( c1, c2, c3, c4 )
VALUES('aaaa', '你好啊', 'cc', 'd'),('eeee', 'fff', NULL, NULL);
现在,表中的记录如下
3.1 — 默认行格式
记录的附加信息是服务器为了描述这条记录而必须添加的一些额外信息,这些附加信息分为三类:“变长字段长度列表”、“NULL值列表”和“记录头信息”。
这里只讲“可变长度字段长度列表”和“NULL值列表”,因为记录头信息很复杂,和本文关系不大,最新面试题整理出来,点击Java面试库小程序在线练题。
3.2 如何知道它到底有多长?——可变长度字段列表
有些变长数据类型,比如(M)、各种TEXT类型、各种BLOB类型,变长数据类型的字段中存储的数据字节数并不固定,在存储真实数据时,还需要存储数据所占用的字节数。
就像设计类型一样,不只是有char数组存储真正的数据,还要有一个变量来记录字符串的长度。比如输入框的最大限制是500个字符,但你还是要有一个变量来统计输入框里实际有多少个字符。同样,也要有一个变量来记录实际的数据长度(“假设是L,后面的描述会为了方便使用”),L代表实际占用的“字节数”,最多分配2个字节来表示这个L,就像short类型一样,2个字节,而寄存器最多有16位可以让你存储这个长度,所以L记录范围是2^16 - 1 = 65535。
❝
这些可变长度字段(举例来说)占用的存储空间分为两部分:
实际数据内容放在相应列中
实际占用的字节数放在变长字段列表部分
❞
我们以测试表中的第一条记录为例,由于测试表的 c1、c2、c4 列都是 (10) 类型,也就是最多 10 个字符,因此在记录的开头需要保存这三列值的长度。“由于测试表中每一列都使用一个字符集,每个字符最多需要 4 个字节来编码(没有使用 utf8,因为可能会存储 emoji 表情,如果只是文本,utf8 就足够了)”,我们来看看第一条记录的变长字段内容的长度:
列名 存储内容 内容长度(十进制表示) 内容长度(十六进制表示)
c1
“啊啊啊”
4字节
0x04
c2
'你好'
9 字节
0x09
c4
‘d’
1 字节
0x01
如何确定这些字段有多少字节?
例如这里c2的“Hello”,使用下面的sql来判断
SELECT LENGTH(c2) from test where c1='aaaa';
每个变长字段数据所占的“字节数”是按照列的顺序“倒序存储”的!!
由于第一行 c1、c2、c4 列的字符串比较短,即实际占用的字节数比较少,因此 L 可以用 1 个字节(8 位)表示。但如果实际占用的字节数较大,则可能需要用 2 个字节(16 位)表示 L。到底能存多少字节呢?请继续阅读。
最新面试题整理完毕,点击Java面试库小程序即可在线练题。
3.3(M)可以存储多少个字符?为什么最大显示为16383?
首先,你需要明白(M)中的M指的是字符数,而不是字节数。
为什么不能是 (20000) 或类似的数字?是因为 20000 个字符放不下吗?
为什么提示符的最大字符数可以是16383个? 这个数字是如何计算出来的?
我得和你好好聊聊这件事!
是变长的。“(64)”可以存储0~64个字符,不一定存储最大64个字符。谁知道这个类型实际存储了多少个字符呢?设计的时候已经考虑到了,但是以字节为单位。后面我们按照对应的字符集换算成字符就可以理解了。变长字段实际占用的字节数是要记录下来的。前面说了,最多分配2个字节(16位)的空间来记录这个L。
❝
它有自己的一套规则。我们引入符号W、M和L:
假设一个字符集最多需要 W 个字节来表示一个字符
对于变长类型(M),该类型最多可以存储M个字符(注意是字符,不是字节)。因此,该类型可以表示的字符串最大占用的字节数为M×W。
假设它实际存储的字节数为L。
❞
我们来看极限边界的情况,为了记录实际存储了多少个“字节”,最多分配2个字节的空间来记录。2个字节有16位,全为1,最多能记录2^16-1,也就是65535个,最多能记录65535个字节,字符集中一个字符占用的字节数最多为4个字节,65535/4=16383.75,只要字符数不超过16383,就能记录实际占用的长度L,如果多的话就记录不下了!所以这就能解释前面那个图了。(20000)是不行的,最多就是16383个字符。
“但是!我要强调,有一个但是!”
“最大行长为 65535 字节”。一行里有很多东西,包括可变长度字段列表、NULL 值列表和记录头信息。你得考虑,如果允许字段为 NULL,NULL 值列表会占用一个字节(只要不超过 8 个字段),而每列字段的可变长度字段的实际长度会占用 1 到 2 个字节。如果字段中的数据太大,就会成为溢出列,字段中的数据会分成很多行进行存储(这个后面会讲,看完 NULL 值列表和溢出列之后可以再回来看这个例子)。所以就算它提示 16383 个字符,你也肯定存不了 16383 个。
扫一扫在手机端查看
-
Tags : mysql修改字段类型 字符数组 字符
我们凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设、网站改版、域名注册、主机空间、手机网站建设、网站备案等方面的需求,请立即点击咨询我们或拨打咨询热线: 13761152229,我们会详细为你一一解答你心中的疑难。