目录
一.整数类型
1. 整数类型及其存储空间和取值范围
2. 整数类型选择原则
3. 常见场景的设计建议
3.1 避免的误区
3.2 字段设计示例
二.字符串类型
1.字符串类型的长度限制选择
1.1. 常用字符串类型
1.2. 常见场景设计建议
1.3. char和varchar的选择
二、硬盘存储和内存
2.1 char(10) 和char(6)的区别
2.2 varchar(100)和varchar(50)都存储50个字符,有什么区别 ?
2.2.1 字段定义的最大长度不同
2.2.2 数据库约束和检查成本
2.2.3 内存和临时存储的使用
三、知识扩展
3.1 varchar存储结构
3.2 VARCHAR 存储示例
3.3 特点与注意事项
三、浮点数和定点数
3.1 浮点数(FLOAT 和 DOUBLE)
特点
适用场景
设计建议
3.2 定点数(DECIMAL)
特点
适用场景
设计建议
3. 3 浮点数和定点数的选择
四、日期和时间类型
4.1 日期和时间类型及其特点
4.2 日期和时间类型的选择
4.3 日期和时间字段设计建议
常见字段设计
小数秒精度
4.4 注意事项
4.5 示例
五. 二进制数据类型
5.1 二进制数据类型概述
5.2 二进制数据类型选择
5.3 设计建议和最佳实践
5.3.1 使用合适的数据类型
5.3.2 考虑存储方式
5.3.3 查询性能优化
5.3.4 示例
六. 枚举和集合
6.1 ENUM 类型
6.2 SET 类型
6.3 ENUM 和 SET 类型的比较
6.4 设计中的考虑事项
在MySQL中,为字段选择合适的类型是非常重要的,因为它直接影响到数据的存储效率、查询性能以及数据完整性。以下是一些关于MySQL字段类型选择的规范和最佳实践:
数据类型 |
存储空间 |
无符号范围 |
有符号范围 |
|
1 字节 |
0 到 255 |
-128 到 127 |
|
2 字节 |
0 到 65535 |
-32768 到 32767 |
|
3 字节 |
0 到 16777215 |
-8388608 到 8388607 |
|
4 字节 |
0 到 4294967295 |
-2147483648 到 2147483647 |
|
8 字节 |
0 到 18446744073709551615 |
-9223372036854775808 到 9223372036854775807 |
TINYINT
就足够了。INT
。BIGINT
。UNSIGNED
),可以扩大数值的取值范围。INT
足够。如果表增长速度非常快(每年几千万行),并预计要长期保存,可以考虑用 BIGINT
。INT UNSIGNED
,这样可表示的正整数范围从 0 到 4,294,967,295,这对大多数应用已足够。TINYINT
(1 字节)。例如,0
表示未处理,1
表示已处理等。TINYINT
或 SMALLINT
足够,除非需要极大范围。INT
(4 字节),对于较大的计数值(如累计金额等),可选择 BIGINT
。INT UNSIGNED
一般够用。BIGINT UNSIGNED
。BIGINT
:BIGINT
会占用更多的存储空间和内存,通常只有在数据量非常大、需要极大范围时才选用。BIGINT
。在大表中,使用小的数据类型可以显著节省空间和加快查询速度。INT UNSIGNED
,在超大规模系统中用 BIGINT UNSIGNED
。TINYINT
,值为 0
表示男、1
表示女。TINYINT UNSIGNED
,范围 0-255,足够。SMALLINT
或 INT
,根据积分范围设定。合理选择整数类型可以有效优化数据库的空间使用和性能。
小知识:
varchar(n)中的数字在5.0以下的版本表示字节,在5.0以上表示字符
例子:varchar(100),在5.0以下表示存储100个字节,5.0以上表示存储100个字符;所以5.0以上,在定义类型的时,期望不超过多少字,可以直接写入在括号中;
字符串类型的长度应根据实际的需求来设置:
- CHAR(n):用于固定长度的字符串(如国家代码 ISO 代码
CHAR(2)
)。char的优点是存储空间固定,所以存储读取速度快。缺点是空间冗余,对于数据量大的表,非固定长度属性使用char字段,空间浪费。- VARCHAR(n):用于可变长度的字符串,是最常用的字符串类型。
n
表示最大字符数,在 UTF-8 编码下,每字符可占用 1-3 字节。合理设置n
的大小可以节省存储空间,提高查询效率。存储的空间根据存储的内容变化,空间长度为L+size,存储内容长度+描述存储内容长度信息,优点就是空间节约,缺点就是读取和存储时候,需要读取信息计算下标,才能获取完整内容。- TEXT:用于较长的文本,适合大段描述信息。
TEXT
不需要指定长度,但因为其存储方式会影响查询性能,建议仅在字段长度不确定的情况下使用。
VARCHAR(50)
,50 个字符足以满足大多数语言的姓名。VARCHAR(100)
,邮箱一般不会超过 100 个字符。VARCHAR(15)
,因为电话号码前通常会包含国家代码,使用 VARCHAR(15)
适合大多数情况。VARCHAR(255)
,如果较长可以使用 TEXT
,但建议避免使用太长的 VARCHAR
。
- 考虑其长度是否相近或者固定,如果某个字段其长度虽然比较长,但是其长度总是近似的,如一般在90个到100个字符之间,甚至是相同的长度。此时比较适合采用CHAR字符类型。比较典型的应用就是MD5哈希值。当利用MD5哈希值来存储用户密码时,就非常使用采用CHAR字符类型。因为其长度是相同的。另外,像用来存储用户的身份证号码等等,一般也建议使用CHAR类型的数据。
- 对于较长的且不固定长度的属性,用varchar
- 字符串的长度
n
不宜过大,通常在实际最大长度的基础上略微加大(10%)即可。- 避免在不必要时使用过大的
VARCHAR
长度(如VARCHAR(255)
),以节省存储空间和提高查询效率。
首先char类型最大存储长度是0-255字符,但是很多时候我们存储一个数据是用不到那么大的空间的,所以通过括号里面的数字来限制空间大小,比如我们确定一个字段最多放10个字符,就可以使用char(10)来限制。
那么char(6)和char(10),每个信息占用的空间分别为10个字符和6个字符,不够限定的大小就是在右侧加空格补齐,会造成空间浪费。
- 硬盘上的存储空间虽然都是根据实际字符长度来分配存储空间的
- 对于内存来说,则不是。其时使用固定大小的内存块(限定的最大值)来保存值。
在 MySQL 中,VARCHAR(100)
和 VARCHAR(50)
都存储 50 个字符时,在存储内容方面没有区别,因为它们都只存储实际数据的字节数和长度信息。然而,它们在设计和实际使用中存在以下几点差异:
VARCHAR(50)
:允许存储最多 50 个字符。VARCHAR(100)
:允许存储最多 100 个字符。虽然在存储 50 个字符时,VARCHAR(100)
和 VARCHAR(50)
实际消耗的空间是相同的,但 VARCHAR(100)
在定义上允许更长的字符串。因此,如果数据超过 50 个字符,VARCHAR(50)
会报错或截断,而 VARCHAR(100)
能存储完整的数据。
较大的 VARCHAR
字段会让数据库在插入和更新数据时花费更多时间检查输入数据的长度。例如:
VARCHAR(100)
字段允许更长的输入,需要数据库多花点时间来检查是否超出上限。VARCHAR(50)
,数据库只需检查是否超过 50 个字符,约束较紧,因此检查成本稍低。在某些情况下(如排序和临时表存储时),数据库可能会根据 VARCHAR
定义的最大长度分配内存或磁盘空间。更大的 VARCHAR
字段定义(如 VARCHAR(100)
)可能会导致更多内存分配和临时存储需求。
VARCHAR
是 MySQL 中用于存储可变长度字符串的数据类型,具有灵活的存储结构。VARCHAR
类型的字段在存储时会保存以下内容:
- 实际字符串数据:
VARCHAR
字段存储实际的字符内容。- 长度信息:为记录字符串的实际长度,
VARCHAR
会额外存储长度信息(1 到 2 字节),用于标明字符串数据的实际字节数。
VARCHAR
的存储结构包含两部分:
utf8mb3
编码下,每个字符最多占 3 字节)。VARCHAR
存储示例假设 VARCHAR(10)
字段中存储字符串 "hello"
:
utf8mb3
编码下,"hello"
由 5 个字符组成,每字符 1 字节,占 5 字节。5
。1 + 5 = 6
字节。VARCHAR
仅存储实际字符内容的字节数,未用满的长度不会占用额外空间(相较于固定长度的 CHAR
)。VARCHAR
的最大长度取决于字符集和 MySQL 存储引擎的限制。utf8mb3
编码下,VARCHAR
字段的最大字符数是 21,844 个字符(65,535 字节的最大行存储限制减去长度字节等元数据)。
- 浮点数: 对于需要小数点的数值,如果精度要求不高,可以使用 FLOAT 或 DOUBLE。
- 定点数: 对于需要高精度计算(无误差)的场景(如金融应用),应使用 DECIMAL 或 NUMERIC 类型,并明确指定精度和小数位数。
FLOAT
和 DOUBLE
)浮点数用于表示具有小数部分的数值,通常用于不需要高精度的计算(如科学计算、统计数据)。
FLOAT
:占用 4 字节,精度约为 7 位有效数字。适合存储精度要求不高的数值数据。DOUBLE
:占用 8 字节,精度约为 15-16 位有效数字。适合存储较大数值,且需要较高精度的数据。0.1 + 0.2 != 0.3
)。FLOAT
和 DOUBLE
能够节省存储空间。FLOAT
时,将数据控制在 7 位有效数字以内。DOUBLE
时,将数据控制在 15 位有效数字以内,以保证数据精度的合理性。DECIMAL
)定点数主要用于存储需要精确的小数数据,尤其适合用于财务数据(如金额、汇率)。
DECIMAL(M, D)
:M
表示总位数,D
表示小数位数。例如,DECIMAL(10, 2)
表示最多 10 位数,其中 2 位为小数,剩下 8 位为整数。M
的大小而定,每 9 位数字占用 4 字节。对于 DECIMAL(10, 2)
,需要 5 字节存储。M
和 D
:M
不宜过大,应以实际需要的精度来设置。例如,金额可以用 DECIMAL(10, 2)
,表示最多 10 位数,2 位小数,适合表示百万级的货币金额。FLOAT
、DOUBLE
):DECIMAL
): 类型 |
占用字节 |
格式 |
范围 |
适用场景 |
|
3 |
|
到 |
仅需存储日期,无需时间的情况 |
|
3 |
|
到 |
仅需存储时间(不含日期)的情况 |
|
1 |
|
到 ,或 |
存储年份,如记录年份字段 |
|
5 (MySQL 5.6+) |
|
到 |
不受时区影响的日期和时间 |
|
4 |
|
到 |
受时区影响的时间戳,记录事件时间点 |
|
5 + f |
|
同 ,支持小数秒精度 |
带微秒精度的日期和时间 |
|
4 + f |
|
同 ,支持小数秒精度 |
带微秒精度的时间戳 |
DATE
:用于仅记录日期而无需时间的场景,例如生日、入职日期等。节省空间且查询效率较高。TIME
:用于存储时间(不包括日期),适合记录持续时间、营业时间等。YEAR
:用于仅需存储年份的场景,如记录年份、年度报表等。较节省空间。DATETIME
:适合不受时区影响的日期和时间数据,通常用于需要记录日期和时间但不需要跨时区的场景(如订单时间)。TIMESTAMP
:用于存储与时区相关的事件时间点,通常适合表示全局事件的时间,如记录系统日志时间。TIMESTAMP
支持自动初始化和更新时间,适用于 created_at
和 updated_at
等字段。DATETIME(f)
和 TIMESTAMP(f)
):DATETIME(f)
或 TIMESTAMP(f)
,其中 f
为小数秒的精度(0 到 6)。created_at
) 和 更新时间(updated_at
):TIMESTAMP
类型,且利用其自动更新特性(DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)。DATETIME
来避免时区转换的复杂性。TIMESTAMP
可以确保跨时区时记录时间的一致性,适用于记录精确的全局事件时间。DATETIME
。DATE
节省存储空间,且查询和存储都更简单。TIME
存储时间数据(如事件持续时间、工时等)。如果需要微秒精度,选择带小数秒的 DATETIME(f)
或 TIMESTAMP(f)
。例如:
DATETIME(3)
:精度到毫秒,适合交易时间等需亚秒级精度的应用。TIMESTAMP
会自动处理时区转换,适用于跨时区应用,而 DATETIME
则不受时区影响。DATETIME
)。假设一个订单表 orders
需要记录创建时间、发货日期和订单处理时长:
CREATE TABLE orders (
order_id INT AUTO_INCREMENT PRIMARY KEY,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 记录订单创建时间 自动初始化
shipped_date DATE, -- 记录订单发货日期
processing_duration TIME -- 记录订单处理时长
);
此设计在保证时区一致性、节省空间和便于查询的基础上选择了合适的日期和时间类型。
在 MySQL 中,二进制数据类型用于存储图片、音频、视频、文件等非文本数据,或者需要精确存储的字符串(如加密内容、哈希值)。MySQL 提供了多种适用于二进制数据的字段类型,包括 BINARY
、VARBINARY
和 BLOB
系列类型。
BINARY
或 VARBINARY
,如哈希值或定长二进制数据。BLOB
系列类型,根据实际数据大小选择合适类型。 类型 |
最大存储空间 |
特点 |
|
字节 |
固定长度的二进制字符串,长度不足会填充 。 |
|
字节 |
可变长度的二进制字符串,根据实际数据长度存储,节省空间。 |
|
255 字节 |
适合小型二进制数据。 |
|
65,535 字节(约 64 KB) |
中型二进制数据,适合较小的图片或文档。 |
|
16,777,215 字节(约 16 MB) |
适合大型文件,如音频和大图片。 |
|
4,294,967,295 字节(约 4 GB) |
超大文件,如视频、完整文档等。 |
在设计数据库时,根据二进制数据的大小和用途选择合适的数据类型:
BINARY(n)
和 VARBINARY(n)
:适合存储较短且固定大小或可变大小的二进制数据(如加密密钥、哈希值等)。BINARY(n)
是固定长度的,如果数据长度小于 n
,系统会填充 0x00
,占满 n
字节。VARBINARY(n)
是可变长度的,根据数据实际长度存储,较为节省空间。BLOB
系列类型:适合存储大数据的二进制数据(如图片、音频、视频文件等)。TINYBLOB
:适合小文件或小数据片段。BLOB
:常用于存储中等大小的文件,如缩略图、文档附件等。MEDIUMBLOB
:适合较大文件,如音乐、高清图片。LONGBLOB
:适合超大文件,如高清视频、超大文档等。BINARY
或 VARBINARY
,如 MD5 哈希可使用 BINARY(16)
,SHA-256 哈希可使用 BINARY(32)
。BLOB
或 TINYBLOB
。MEDIUMBLOB
或 LONGBLOB
。BLOB
数据存储在单独的表空间中,因此大量 BLOB
数据字段会增加数据库的负载。定期维护和备份对性能尤为重要。BLOB
字段:二进制数据查询开销较大,频繁读取 BLOB
字段会影响性能。可使用缩略图或引用的方式,减少直接读取大数据的需求。假设一个表 documents
存储不同类型的文件(如缩略图、文件内容等):
CREATE TABLE documents (
doc_id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(100),
thumbnail TINYBLOB, -- 存储小型的图片缩略图
content MEDIUMBLOB, -- 存储较大的文件内容
checksum BINARY(32) -- 存储文件的 SHA-256 校验和
);
在这个设计中:
thumbnail
使用 TINYBLOB
,适合小型图片。content
使用 MEDIUMBLOB
,适合中等大小的文件内容。checksum
使用 BINARY(32)
存储文件校验和。ENUM
类型:适用于值的选择是互斥的(如性别、状态),且只有一个选项。SET
类型:适用于字段可以选择多个值的情况(如用户权限、标签、分类等),但需要注意查询性能和数据的复杂性。ENUM
类型ENUM
类型用于表示一个字段只能从一组预定义的值中选择一个。每个 ENUM
类型的字段存储的值是一个整数,这个整数代表在定义值集合中的位置,尽管存储的实际上是该位置对应的文本值。
ENUM('value1', 'value2', 'value3', ...)
ENUM
类型在内部使用整数表示,每个选项都会被赋予一个从 1
开始的数字,这使得存储空间非常高效。NULL
。ENUM
内部存储的是选项的位置(从 1 开始),而不是字符串,因此可以根据位置值来进行排序。ENUM
值不宜过多(一般不要超过 10-20 个),超过 20 个时建议考虑使用其他表存储(例如通过外键引用一个常量表)。ENUM
类型时,存储的是一个整数,但它的顺序值是根据定义顺序来分配的。注意修改顺序时可能会导致数据含义改变。CREATE TABLE employees (
employee_id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100),
gender ENUM('Male', 'Female', 'Other') NOT NULL, -- 性别
status ENUM('Active', 'Inactive', 'On Leave') DEFAULT 'Active' -- 状态
);
在此示例中:
gender
字段只能取 'Male'
、'Female'
或 'Other'
。status
字段默认值为 'Active'
,并且只能取 'Active'
、'Inactive'
或 'On Leave'
。SET
类型SET
类型与 ENUM
类型类似,不同之处在于 SET
可以存储多个值,而 ENUM
只能存储一个值。SET
类型适用于字段值可以选择多个项的场景。
SET('value1', 'value2', 'value3', ...)
SET
类型内部存储为一个整数,其中每一位对应一个集合的选项。如果多个选项被选择,则每一位的值都为 1,表示该选项被选中。SET
值的顺序是有意义的,因此它会按照集合定义的顺序存储。SET
允许多个值同时存储,但为了简化数据管理和提高查询效率,不建议选择过多的选项。SET
类型的数据存储方式是按位存储(每个选项占一位),查询时可能需要通过位运算来筛选数据,处理时稍显复杂。SET
类型确保每个选项最多只能选中一次,因此不支持重复选项。CREATE TABLE products (
product_id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100),
tags SET('Electronics', 'Clothing', 'Furniture', 'Toys', 'Sports') -- 商品标签
);
在此示例中:
tags
字段存储多个选项(如 'Electronics'
、'Clothing'
等)。('Electronics', 'Toys')
,表示它既是电子产品也是玩具。ENUM
和 SET
类型的比较 特性 |
|
|
存储多个值 |
不支持,仅能选择一个值 |
支持,最多 64 个选项,可以选择多个值 |
存储方式 |
存储为整数,表示选中的位置 |
存储为整数,按位表示选中的多个值 |
使用场景 |
用于选择单一值,如性别、状态、等级等 |
用于选择多个值,如标签、角色、权限等 |
查询复杂性 |
简单,直接通过值查询 |
需要使用位运算来查询多个选项 |
支持的最大项数 |
65,535 个选项 |
64 个选项 |
默认值 |
可指定一个默认值,通常为某个有效值 |
可指定默认值,但不常用 |
空间效率 |
较高,存储为一个整数 |
由于位操作存储,效率较高,适用于小集合 |
ENUM
和 SET
都确保只能存储预定义的值,因此它们在数据验证方面非常有用,能够减少无效数据的插入。ENUM
或 SET
。SET
类型有 64 个选项时),可能会导致查询性能下降。此时可以通过使用关联表(M:N
关系)来避免性能瓶颈。