MYSQL的列类型和占用空间

本文介绍了MySQL支持的各种数据类型,包括数值类型、日期/时间类型和字符串类型。详细列举了每种类型的有效值范围、存储需求及其特点。

MySQL支持多种列类型:数值类型、日期/时间类型和字符串(字符)类型。

数值类型

类型

字节

最小值

最大值

 

 

(带符号的/无符号的)

(带符号的/无符号的)

TINYINT

1

-128

127

 

 

0

255

SMALLINT

2

-32768

32767

 

 

0

65535

MEDIUMINT

3

-8388608

8388607

 

 

0

16777215

INT

4

-2147483648

2147483647

 

 

0

4294967295

BIGINT

8

-9223372036854775808

9223372036854775807

 

 

0

18446744073709551615


表示时间值的DATE和时间类型为DATETIME、DATE、TIMESTAMP、TIME和YEAR。每个时间类型有一个有效值范围和一个“”值

列类型

”值

DATETIME

'0000-00-00 00:00:00'

DATE

'0000-00-00'

TIMESTAMP

00000000000000

TIME

'00:00:00'

YEAR

0000


字符串类型的存储需求

列类型

存储需求

CHAR(M)

M个字节,0 <= M <= 255

VARCHAR(M)

L+1个字节,其中L <= M 且0 <= M <= 65535(参见下面的注释)

BINARY(M)

M个字节,0 <= M <= 255

VARBINARY(M)

L+1个字节,其中L <= M 且0 <= M <= 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('value1','value2',...)

1或2个字节,取决于枚举值的个数(最多65,535个值)

SET('value1','value2',...)

1、2、3、4或者8个字节,取决于set成员的数目(最多64个成员)


VARCHAR、BLOB和TEXT类是变长类型。每个类型的存储需求取决于列值的实际长度(用前面的表中的L表示),而不是该类型的最大可能的大小。例如,VARCHAR(10)列可以容纳最大长度为10的字符串。实际存储需求是字符串(L)的长度,加上一个记录字符串长度的字节。对于字符串'abcd',L是4,存储需要5个字节。

对于CHAR、VARCHAR和TEXT类型,前面的表中的值L和M应解释为字符数目,并且列定义中的这些类型的长度表示字符数目。例如,要想保存一个TINYTEXT值需要L字符+ 1个字节。

ARCHAR列的有效最大长度为65,532字符。
<think>好的,我现在需要回答用户关于MySQL如何计算单行数据占用空间的问题。首先,我得回忆一下MySQL存储结构的相关知识。用户提到了几个引用,其中引用34可能特别相关,因为它们涉及NULL值、varchar存储以及空间计算。首先,用户想知道计算单行数据的方法或公式。根据已有的知识,MySQL的行格式(如CompactDynamic)会影响存储方式。Compact行格式是常用的,所以可能需要从这里入手。接下来,行空间的计算包括几个部分:固定长度的列、可变长度的列、NULL值标记、行头信息等。比如,每个NULL值的列在Compact格式中会占用一个位,但不会存储实际数据。这点需要确认是否正确,可能引用3中提到NULL值是否占用空间,答案是不占用,但需要位标记。然后,varchar这样的可变长度类型,存储时占用实际长度加上长度标识符(1或2字节)。例如,varchar(255)如果实际存储10个字符,且字符集是latin1,那么占用10+1=11字节。如果是utf8mb4,可能需要4*10+1=41字节?这里需要考虑字符集的影响。另外,行头信息在Compact格式中占用5字节,再加上可变长度列的数量占用的1或2字节。例如,如果有两个varchar列,可能需要1字节来记录数量。这部分需要详细计算。 然后,行溢出处理。当行数据超过页大小时,会存储部分数据在溢出页中。默认页大小是16KB,所以如果数据超过这个限制,就需要处理溢出。但用户的问题可能更关注常规情况下的计算,所以可能需要先说明常规计算,再提溢出情况。 引用4中提到的空间计算示例,比如每个记录大约50字节,这可能是一个粗略的估计,但用户需要具体的公式。因此需要将各个部分拆解成公式,比如:总空间=行头+NULL位图 +固定长度列+可变长度列+其他开销每个部分的具体计算方式需要详细说明。例如,固定长度列如int、date等,直接占用固定字节数。可变长度列如varchar、text等,需要加上长度标识符实际数据。 举个例子,假设有一行数据包含:INT(4字节),VARCHAR(100)存储了20个字符(使用utf8mb4,每个字符4字节),两个NULL值,一个非NULL的TINYINT(1字节)。那么计算如下: 行头:5字节NULL位图:计算列数,假设表有4列,那么NULL位图需要(4 +7)/8=1字节。这里可能需要更准确的公式,比如ceil(number_of_columns/8)。固定长度列:INT(4)+ TINYINT(1)=5字节,但如果有两个NULL列,比如其中两列是允许NULL的,那么它们的空间会被节省吗?比如,如果某列是INT且允许NULL,当它为NULL时,固定长度部分不占用空间?或者无论是否为NULL,固定长度列都占用空间?这里可能存在误区,需要确认。根据MySQL的文档,对于固定长度的列,如果允许NULL,当值为NULL时,不会占用存储空间。而可变长度列如果为NULL,同样不占用空间。因此,在计算时需要考虑列是否为NULL。例如,如果表中的列是:idINT NOTNULL(4字节) nameVARCHAR(100)NULL(实际长度+1或2字节) ageTINYINTNULL(1字节,但如果为NULL则不占用) 那么,如果age为NULL,那么固定长度部分只有id的4字节,而age不占空间。可变长度部分name如果为NULL,则不占用空间,否则占用实际长度+1或2字节。这可能会影响计算方式,所以公式需要根据列的类型是否为NULL来调整。 另外,可变长度列的数量会影响行头中的长度存储。例如,如果有M个可变长度列,那么需要1或2字节来存储它们的长度,具体取决于数量。如果M<255,用1字节,否则用2字节。这部分也需要计入总空间。最后,需要考虑行格式的其他开销,比如记录头信息(5字节)、事务ID回滚指针(如果存在的话,例如InnoDB的聚簇索引记录会有这些)。但用户的问题可能集中在用户数据的存储,而不是系统字段。例如,InnoDB每行会有额外的6字节事务ID7字节回滚指针,但可能只在某些情况下存在?需要确认。例如,在InnoDB中,每行记录除了用户定义的数据外,还有6字节的事务ID7字节的回滚指针,以及一些其他头信息。这部分是否应该计入单行空间?如果用户的问题是关于物理存储空间,那么这些系统字段也需要考虑进去。综合这些因素,计算单行空间的公式可能比较复杂,需要分步骤说明。可能需要将各个部分拆解,并给出示例。现在,根据这些思考,整理出一个结构清晰的回答,分步骤说明如何计算,并给出公式示例。同时,引用相关的引用资料,如引用3提到的Compact行格式,引用4中的空间计算示例作为参考。</think>### MySQL单行数据空间计算方法 #### 1. **行格式的影响** MySQL的存储空间计算与行格式密切相关,默认使用**Compact**格式(InnoDB引擎)。不同行格式对NULL值、可变长度字段的处理方式不同[^3]。 #### 2. **计算公式** 单行数据占用的总空间 = **固定长度列空间** + **可变长度列空间** + **NULL值标记位** + **行头信息** + **系统字段** 具体分解如下: 1. **固定长度列** - 非NULL值:直接占用定义的大小(如`INT`占4字节,`DATE`占3字节)。 - NULL值:不占用空间(但需在NULL位图中标记)。 2. **可变长度列** - 非NULL值:实际数据长度 + **长度标识符**(1或2字节,取决于最大可能长度)。 - 例如:`VARCHAR(255)`实际存储"abc",字符集为utf8mb4时占`3*4 + 1 = 13`字节(长度标识符1字节)。 - NULL值:不占用空间。 3. **NULL值标记位** - 每8个允许NULL的列占用1字节。 - 公式:`CEILING(允许NULL的列数 / 8)`。 4. **行头信息** - Compact格式固定占用**5字节**,包含记录类型、下一条记录指针等[^3]。 5. **系统字段** - InnoDB引擎每行额外包含**6字节事务ID****7字节回滚指针**(用于MVCC)。 #### 3. **示例计算** 假设表结构如下: ```sql CREATE TABLE users ( id INT NOT NULL, -- 固定长度(4字节) name VARCHAR(100) NULL, -- 可变长度(最大100字符) age TINYINT NULL, -- 固定长度(1字节) bio VARCHAR(255) NOT NULL -- 可变长度(最大255字符) ); ``` 某行数据为: `id=123`, `name=NULL`, `age=NULL`, `bio='Hello'`(字符集为latin1)。 1. **固定长度列**:`id`占4字节(`age`为NULL不占用)。 2. **可变长度列**: - `name`为NULL,不占用。 - `bio`占`5 + 1 = 6`字节(实际数据5字符,长度标识符1字节)。 3. **NULL位图**:允许NULL的列数为2(`name``age`),需`CEILING(2/8) = 1`字节。 4. **行头**:5字节。 5. **系统字段**:6 + 7 = 13字节。 **总空间**: $$4 + 6 + 1 + 5 + 13 = 29 \text{字节}$$ #### 4. **行溢出处理** - 若单行数据超过**页大小的一半**(默认页16KB,即8KB),MySQL会将部分数据存储到溢出页中[^3]。 - 此时行内仅保留768字节前缀,其余存入溢出页。 #### 5. **验证方法** - 使用`SHOW TABLE STATUS`查看表的平均行大小(`Avg_row_length`)。 - 通过InnoDB系统表`INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES`查看精确数据页信息[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

day walker

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值