磁盘上表数据的存储要求取决于几个因素。不同的存储引擎以不同的方式表示数据类型和存储原始数据,可能会对表或列的存储要求进行压缩。
尽管磁盘上的存储布局不同,但 MySQL 的内部 API 在交换表行信息时使用了一致的数据结构,这适用于所有存储引擎。
本节包括每种数据类型的存储要求指南和信息,包括固定大小表示的存储引擎的内部格式和大小。
表的内部表示的最大行大小为 65,535 字节,即使存储引擎能够支持更大的行。这个数字不包括 BLOB
或 TEXT
列,这些列只占用 9 到 12 字节的大小。对于 BLOB
和 TEXT
数据,信息存储在不同的内存区域中,而不是行缓冲区中。不同的存储引擎以不同的方式处理这些数据的分配和存储。有关更多信息,请参阅 第 18 章 替代存储引擎 和 第 10.4.7 节“表列数和行大小限制”。
NDB
表使用 4 字节对齐;所有 NDB
数据存储以 4 字节的倍数进行。因此,一个通常需要 15 字节的列值在 NDB
表中需要 16 字节。例如,在 NDB
表中,TINYINT
、SMALLINT
、MEDIUMINT
和 INTEGER
(INT
)每个列类型都需要 4 字节的存储空间,因为对齐因子。
每个 BIT(
列占用 M
)M
位存储空间。虽然单个 BIT
列不是 4 字节对齐的,NDB
为每行保留 4 字节(32 位)用于第一个 1-32 位需要的 BIT
列,然后是另一个 4 字节用于 33-64 位,以此类推。
虽然 NULL
本身不需要任何存储空间,NDB
如果表定义中包含任何允许 NULL
的列,则每行保留 4 字节,直到 32 个 NULL
列。(如果 NDB 集群表定义了超过 32 个 NULL
列,直到 64 个 NULL
列,则每行保留 8 字节。)
每个使用 NDB
存储引擎的表都需要一个主键;如果您没有定义主键,NDB
将创建一个“隐藏”的主键。这个隐藏的主键每个表记录占用 31-35 字节。
您可以使用 ndb_size.pl Perl 脚本来估算 NDB
存储需求。它连接到当前 MySQL(不是 NDB 集群)数据库,并创建一个报告,说明该数据库如果使用 NDB
存储引擎将需要多少空间。请参阅 第 25.5.29 节,“ndb_size.pl — NDBCLUSTER 大小需求估算器” 以获取更多信息。
Data Type | Storage Required |
---|---|
TINYINT |
1 字节 |
SMALLINT |
2 字节 |
MEDIUMINT |
3 字节 |
INT , INTEGER |
4 字节 |
BIGINT |
8 字节 |
FLOAT( |
如果 0 <= p <= 24,则 4 字节;如果 25 <= p <= 53,则 8 字节 |
FLOAT |
4 字节 |
DOUBLE [PRECISION] , REAL |
8 字节 |
DECIMAL( , NUMERIC( |
见以下讨论 |
BIT( |
约 (M +7)/8 字节 |
对于 DECIMAL
(和 NUMERIC
)列,值使用二进制格式表示,九个十进制(base 10)数字被打包到四个字节中。整数和小数部分的存储分别确定。每九个数字需要四个字节,剩余的数字需要四个字节的一部分。存储要求如下表所示。
Leftover Digits | Number of Bytes |
---|---|
0 | 0 |
1 | 1 |
2 | 1 |
3 | 2 |
4 | 2 |
5 | 3 |
6 | 3 |
7 | 4 |
8 | 4 |
对于 TIME
, DATETIME
和 TIMESTAMP
列,对于在 MySQL 5.6.4 之前创建的表和从 5.6.4 开始创建的表,存储要求不同。这是因为 5.6.4 中的更改,允许这些类型具有小数部分,需要 0 到 3 字节。
Data Type | Storage Required Before MySQL 5.6.4 | Storage Required as of MySQL 5.6.4 |
---|---|---|
YEAR |
1 字节 | 1 字节 |
DATE |
3 字节 | 3 字节 |
TIME |
3 字节 | 3 字节 + 小数秒存储 |
DATETIME |
8 字节 | 5 字节 + 小数秒存储 |
TIMESTAMP |
4 字节 | 4 字节 + 小数秒存储 |
从 MySQL 5.6.4 开始,对于 YEAR
和 DATE
,存储要求保持不变。然而,TIME
, DATETIME
和 TIMESTAMP
表示方式不同。DATETIME
被打包得更紧凑,需要 5 个字节,而不是 8 个字节,所有三个部分都有一个小数部分,需要 0 到 3 字节,取决于存储值的小数秒精度。
Fractional Seconds Precision | Storage Required |
---|---|
0 | 0 字节 |
1, 2 | 1 字节 |
3, 4 | 2 字节 |
5, 6 | 3 字节 |
例如,TIME(0)
,TIME(2)
,TIME(4)
和 TIME(6)
分别使用 3、4、5 和 6 字节。TIME
和 TIME(0)
是等效的,需要相同的存储空间。
有关时间值内部表示的详细信息,请参阅 MySQL Internals: Important Algorithms and Structures。
在以下表格中,M
代表非二进制字符串类型的声明列长度(以字符为单位)和二进制字符串类型的字节长度。 L
代表给定字符串值的实际字节长度。
Data Type | Storage Required |
---|---|
CHAR( |
InnoDB 行格式的紧凑家族优化了可变长度字符集的存储。见 COMPACT 行格式存储特征。否则,M × w 字节,<= 255,其中 w 是字符集中最大长度字符所需的字节数。 |
BINARY( |
M 字节,0 <= 255 |
VARCHAR( , VARBINARY( |
L + 1 字节,如果列值需要 0 − 255 字节,L + 2 字节,如果值可能需要超过 255 字节 |
TINYBLOB , TINYTEXT |
L + 1 字节,其中 L < 28 |
BLOB , TEXT |
L + 2 字节,其中 L < 216 |
MEDIUMBLOB , MEDIUMTEXT |
L + 3 字节,其中 L < 224 |
LONGBLOB , LONGTEXT |
L + 4 字节,其中 L < 232 |
ENUM(' |
1 或 2 字节,取决于枚举值的数量(最大 65,535 个值) |
SET(' |
1、2、3 或 8 字节,取决于集合成员的数量(最大 64 个成员) |
可变长度字符串类型使用长度前缀加数据来存储。长度前缀需要从 1 到 4 字节,取决于数据类型,值为 L
(字符串的字节长度)。例如,存储 MEDIUMTEXT
值需要 L
字节来存储值加 3 字节来存储值的长度。
要计算特定CHAR
、VARCHAR
或TEXT
列值所需的字节数,您必须考虑该列使用的字符集和该值是否包含多字节字符。特别是,当使用 UTF-8 Unicode 字符集时,您必须牢记不是所有字符都使用相同数量的字节。utf8mb3
和utf8mb4
字符集可以分别需要每个字符 3 和 4 个字节。有关utf8mb3
或utf8mb4
字符的存储使用情况的详细信息,请参阅第 12.9 节,“Unicode 支持”。
VARCHAR
、VARBINARY
和BLOB
和TEXT
类型是可变长度类型。对于每种类型,存储要求取决于以下因素:
-
列值的实际长度
-
列的最大可能长度
-
列使用的字符集,因为一些字符集包含多字节字符
例如,VARCHAR(255)
列可以容纳最多 255 个字符的字符串。假设该列使用latin1
字符集(每个字符一个字节),则实际存储要求是字符串的长度(L
),加上一个字节来记录字符串的长度。对于字符串'abcd'
,L
是 4,存储要求是五个字节。如果同一列改用ucs2
双字节字符集,存储要求是 10 个字节:字符串'abcd'
的长度是八个字节,列需要两个字节来存储长度,因为最大长度大于 255(最多 510 字节)。
在VARCHAR
或VARBINARY
列中,实际可以存储的最大字节数受 65,535 字节的最大行大小限制,该限制与所有列共享。对于使用多字节字符的VARCHAR
列,实际可以存储的最大字符数较少。例如,utf8mb4
字符可以需要每个字符四个字节,因此使用utf8mb4
字符集的VARCHAR
列可以声明为最多 16,383 个字符。请参阅第 10.4.7 节,“表列计数和行大小限制”。
InnoDB
将长度大于或等于 768 字节的固定长度字段编码为可变长度字段,可以存储在页面外。例如,CHAR(255)
列可以超过 768 字节,如果字符集的最大字节长度大于 3,如utf8mb4
。
The NDB
存储引擎支持可变宽度列。这意味着VARCHAR
列在 NDB Cluster 表中的存储要求与其他存储引擎相同,唯一的例外是这些值是 4 字节对齐的。因此,在VARCHAR(50)
列中使用latin1
字符集的字符串'abcd'
需要 8 字节(而不是 5 字节,如同在MyISAM表中的情况)。
TEXT
、 BLOB
和 JSON
列在 NDB
存储引擎中实现不同,其中每个列中的每一行由两个独立部分组成。一个是固定大小(256字节用于 TEXT
和 BLOB
,4000字节用于 JSON
),实际存储在原始表中。另一个是超过256字节的任何数据,存储在隐藏的 blob 部分表中。该表中的行大小由列的确切类型确定,如下表所示:
Type | Blob Part Size |
---|---|
BLOB 、 TEXT |
2000 |
MEDIUMBLOB 、 MEDIUMTEXT |
4000 |
LONGBLOB 、 LONGTEXT |
13948 |
JSON |
8100 |
这意味着 TEXT
列的大小是256,如果 size
<= 256(其中 size
代表行的大小);否则,大小是256 + size
+ (2000 × (size
− 256) % 2000)。
对于 TINYBLOB
或 TINYTEXT
列值,NDB
不会单独存储 blob 部分。
您可以使用 NDB_COLUMN
在创建或修改父表时,在列注释中增加 NDB
blob 列的 blob 部分的大小,直到最大值13948。NDB
还支持使用 NDB_TABLE
在列注释中设置 TEXT
、BLOB
或 JSON
列的inline大小。请参阅 NDB_COLUMN 选项,以获取更多信息。
枚举对象的大小由不同的枚举值确定。对于最多255个可能的枚举值,使用一个字节。对于256到65,535个可能的枚举值,使用两个字节。请参阅 第13.3.5节,“ENUM类型”。
集合对象的大小由不同的集合成员确定。如果集合的大小是 N
,则对象占用 (
字节,四舍五入到1、2、3、4或8字节。集合最多可以有64个成员。请参阅 第13.3.6节,“SET类型”。N
+7)/8
MySQL 使用4个字节来指示SRID,然后是值的WKB表示形式。LENGTH()
函数返回值存储所需的字节数。
有关WKB和空间值内部存储格式的描述,请参阅 第13.4.3节,“支持的空间数据格式”。
一般来说,JSON
列的存储要求大致相同于 LONGBLOB
或 LONGTEXT
列;也就是说,JSON 文档所占用的空间大致相同于将文档的字符串表示形式存储在这些类型的列中的空间。然而,由于二进制编码、元数据和用于查找的字典,JSON 文档中的单个值存储会带来一些开销。例如,在 JSON 文档中存储的字符串需要额外 4 到 10 字节的存储空间,具体取决于字符串的长度和它所在的对象或数组的大小。
此外,MySQL 对存储在 JSON
列中的任何 JSON 文档的大小施加了限制,使其不能超过 max_allowed_packet
的值。