表数据在磁盘上的存储要求取决于几个因素。不同的存储引擎代表数据类型,存储原始数据的方式也不同。表数据可能会针对一列或整行进行压缩,从而使表或列的存储需求计算变得复杂。
尽管磁盘上的存储布局存在差异,但用于通信和交换表行信息的内部 MySQL API 使用适用于所有存储引擎的一致数据结构。
本节包括有关 MySQL 支持的每种数据类型的存储要求的指南和信息,包括使用固定大小的数据类型表示的存储引擎的内部格式和大小。信息按类别或存储引擎列出。
表的内部表示具有 65,535 字节的最大行大小,即使存储引擎能够支持更大的行也是如此。此图不包括
BLOB
或
TEXT
列,它们仅占此大小的 9 到 12 个字节。对于
BLOB
和
TEXT
数据,信息在内部存储在与行缓冲区不同的内存区域中。不同的存储引擎根据它们用于处理相应类型的方法,以不同的方式处理此数据的分配和存储。有关详细信息,请参阅第 15 章,替代存储引擎和
第 8.4.7 节,“表列数和行大小的限制”。
NDB
表使用
4 字节对齐;所有
NDB
数据存储都以 4 字节的倍数进行。因此,通常需要 15 个字节的列值在
NDB
表中需要 16 个字节。例如,在
NDB
表中,
由于对齐因子TINYINT
,
SMALLINT
、
MEDIUMINT
、 和
INTEGER
( INT
) 列类型每条记录都需要 4 个字节的存储空间。
每
列占用一些存储空间。尽管单个
列
不是4 字节对齐的,
但每行为列所需的前 1-32 位保留 4 个字节(32 位)
,然后为第 33-64 位保留另外 4 个字节,依此类推。
BIT(
M
)M
BIT
NDB
BIT
虽然 aNULL
本身不需要任何存储空间,NDB
但如果表定义包含任何定义为 的列,则每行保留 4 个字节NULL
,最多 32
NULL
列。(如果 NDB Cluster 表定义了超过 32NULL
列,最多 64NULL
列,则每行保留 8 个字节。)
每个使用NDB
存储引擎的表都需要一个主键;如果您没有定义主键,则创建一个“隐藏”主键
NDB
。这个隐藏的主键每条表记录占用 31-35 个字节。
您可以使用ndb_size.pl Perl 脚本来估计NDB
存储需求。NDB
它连接到当前的 MySQL(不是 NDB Cluster)数据库,并创建一个报告,说明如果使用存储引擎,该数据库将需要多少空间。有关更多信息,请参阅第 21.5.28 节,“ndb_size.pl — NDBCLUSTER 大小需求估计器”。
数据类型 | 需要存储 |
---|---|
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
使用二进制格式表示,该格式将九个十进制(基数 10)数字打包成四个字节。每个值的整数和小数部分的存储分别确定。九个数字的每个倍数需要四个字节,而“剩余”
数字需要四个字节的一部分。下表给出了多余数字所需的存储空间。
剩余数字 | 字节数 |
---|---|
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 个字节。
数据类型 | MySQL 5.6.4 之前的存储要求 | 从 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 个字节的小数部分,具体取决于存储值的小数秒精度。
小数秒精度 | 需要存储 |
---|---|
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
表示给定字符串值的实际长度(以字节为单位)。
数据类型 | 需要存储 |
---|---|
CHAR( |
紧凑的 InnoDB 行格式系列优化了可变长度字符集的存储。请参阅
COMPACT 行格式存储特性。否则,M ×
w bytes, 255,其中
是字符集中最大长度字符所需的字节数。<=
w |
BINARY( |
M 字节,0 255<=
|
VARCHAR( ,
VARBINARY( |
L + 1 个字节,如果列值需要 0 − 255 个字节,L + 2 个字节,如果值可能需要超过 255 个字节 |
TINYBLOB ,
TINYTEXT |
L + 1 个字节,其中
L < 2 8 |
BLOB ,TEXT |
L + 2 字节,其中
L < 2 16 |
MEDIUMBLOB ,
MEDIUMTEXT |
L + 3 个字节,其中
L < 2 24 |
LONGBLOB ,
LONGTEXT |
L + 4 字节,其中
L < 2 32 |
ENUM(' |
1 或 2 个字节,取决于枚举值的数量(最多 65,535 个值) |
SET(' |
1、2、3、4 或 8 个字节,具体取决于集合成员的数量(最多 64 个成员) |
可变长度字符串类型使用长度前缀和数据存储。长度前缀根据数据类型需要一到四个字节,前缀的值为
L
(字符串的字节长度)。例如,一个
MEDIUMTEXT
值的存储需要
L
字节来存储值加上三个字节来存储值的长度。
要计算用于存储特定
CHAR
、
VARCHAR
或
TEXT
列值的字节数,您必须考虑用于该列的字符集以及该值是否包含多字节字符。特别是,在使用utf8
Unicode 字符集时,必须记住并非所有字符都使用相同的字节数。utf8mb3
和utf8mb4
字符集可能分别要求每个字符最多三个和四个字节。有关用于不同类别utf8mb3
或
utf8mb4
字符的存储的细分,请参阅
第 10.9 节,“Unicode 支持”。
VARCHAR
,
VARBINARY
, 和
BLOB
and
TEXT
类型是变长类型。对于每一个,存储要求取决于以下因素:
列值的实际长度
列的最大可能长度
列使用的字符集,因为有些字符集包含多字节字符
例如,一VARCHAR(255)
列可以容纳最大长度为 255 个字符的字符串。假设列使用latin1
字符集(每个字符一个字节),实际需要存储的是字符串的长度(L
),加上一个字节来记录字符串的长度。对于字符串
'abcd'
,L
是 4,存储要求是五个字节。如果同一列改为声明使用ucs2
双字节字符集,则存储要求为 10 个字节: 的长度'abcd'
为 8 个字节,该列需要两个字节存储长度,因为最大长度大于 255(最多 510字节)。
或
列中可以存储的
最大有效字节数受最大行大小 65,535 字节的限制,该行大小由所有列共享。对于存储多字节字符的列,有效的最大字符数更少。例如,
字符每个字符最多需要三个字节,因此
使用该字符集的列可以声明为最多 21,844 个字符。请参阅
第 8.4.7 节,“表列数和行大小的限制”。
VARCHAR
VARBINARY
VARCHAR
utf8mb3
VARCHAR
utf8mb3
InnoDB
将长度大于或等于 768 字节的固定长度字段编码为可变长度字段,可以存储在页外。例如,
CHAR(255)
如果字符集的最大字节长度大于 3,则列可以超过 768 个字节,就像utf8mb4
.
NDB
存储引擎支持可变宽度的列
。这意味着
VARCHAR
NDB Cluster 表中的列需要与任何其他存储引擎相同的存储量,除了这些值是 4 字节对齐的。因此,'abcd'
存储在
VARCHAR(50)
使用字符集的列中的
字符串latin1
需要 8 个字节(而不是
MyISAM
表中相同列值的 5 个字节)。
TEXT
,
BLOB
, 和
JSON
列在NDB
存储引擎中的实现方式不同,其中列中的每一行由两个独立的部分组成。其中之一是固定大小(256 字节用于
TEXT
和BLOB
,4000 字节用于JSON
),并且实际存储在原始表中。另一个包含超过 256 字节的任何数据,存储在隐藏的 blob 部分表中。第二个表中行的大小由列的确切类型决定,如下表所示:
类型 | 斑点部分大小 |
---|---|
BLOB ,TEXT |
2000 |
MEDIUMBLOB ,
MEDIUMTEXT |
4000 |
LONGBLOB ,
LONGTEXT |
13948 |
JSON |
8100 |
这意味着
TEXT
如果
size
<= 256(其中
size
表示行的大小),则列的大小为 256;否则,大小为 256 +
size
+ (2000 × ( size
− 256) % 2000)。
没有 blob 部分由NDB
forTINYBLOB
或TINYTEXT
列值单独存储。
您可以在创建或更改父表时使用列注释将NDB
blob 列的 blob 部分的大小增加到最大值 13948
。NDB_COLUMN
有关详细信息,请参阅
NDB_COLUMN 选项。
对象的大小ENUM
由不同枚举值的个数决定。一个字节用于具有最多 255 个可能值的枚举。两个字节用于具有 256 到 65,535 个可能值的枚举。请参阅第 11.3.5 节,“ENUM 类型”。
对象的大小SET
由不同集合成员的数量决定。如果设置大小为N
,则对象占用
字节,四舍五入为 1、2、3、4 或 8 字节。A
最多可以有 64 个成员。请参阅第 11.3.6 节,“SET 类型”。
(
N
+7)/8SET
MySQL 使用 4 个字节存储几何值以指示 SRID,后跟该值的 WKB 表示形式。该
LENGTH()
函数返回值存储所需的字节空间。
有关空间值的 WKB 和内部存储格式的说明,请参阅第 11.4.3 节,“支持的空间数据格式”。
通常,列的存储要求
与或
列的存储要求JSON
大致相同;也就是说,JSON 文档消耗的空间与存储在其中一种类型的列中的文档的字符串表示形式大致相同。但是,存储在 JSON 文档中的各个值的二进制编码(包括查找所需的元数据和字典)会产生开销。例如,存储在 JSON 文档中的字符串需要 4 到 10 个字节的额外存储空间,具体取决于字符串的长度和存储它的对象或数组的大小。
LONGBLOB
LONGTEXT
此外,MySQL 对JSON
列中存储的任何 JSON 文档的大小施加了限制,因此它不能大于
max_allowed_packet
.