04.MySQL数据类型详解

news2025/6/3 15:32:51

MySQL数据类型详解


文章目录

  1. MySQL数据类型
  2. 数据类型分类
  3. 数值类型
    • tinyint类型
    • bit类型
    • float类型
    • decimal类型
  4. 字符串类型
    • char类型
    • varchar类型
    • char和varchar比较
  5. 时间日期类型
  6. enum和set类型
  7. 数据类型选择的进阶技巧
  8. 常见误区与解决方案
  9. 性能优化与最佳实践

MySQL数据类型

数据类型的作用

数据类型不仅是存储数据的容器,更是数据库设计的基石。它决定了三个核心要素:

  1. 存储空间:例如,存一个整数和一篇长文显然需要不同的空间分配策略。
  2. 二进制解析方式:同一串二进制数据,用INT解读是数字,用CHAR解读可能变成乱码。
  3. 取值范围限制:年龄不可能是负数,性别只能是有限选项,这些都需要数据类型来规范。

此外,数据类型还影响索引效率、查询优化器的选择,甚至影响数据库的扩展性和维护成本。例如,错误地使用VARCHAR(255)存储固定长度的MD5值会导致空间浪费和查询效率下降。


数据类型分类

MySQL的数据类型大致可分为四类,以下是详细分类表:

分类数据类型说明
数值类型BIT(M)位类型,M默认1,范围1-64位
BOOL布尔值(实际是TINYINT(1))
TINYINT/SMALLINT/MEDIUMINT/INT/BIGINT整型家族,字节数从1到8递增
FLOAT/DOUBLE/DECIMAL浮点数和精确小数
字符串类型CHAR(L)固定长度字符串(最大255)
VARCHAR(L)可变长度字符串(最大65535字节)
BLOB/TEXT大文本/二进制数据
日期时间类型DATE/DATETIME日期格式YYYY-MM-DD,时间戳
TIMESTAMP自动更新的时间戳
集合类型ENUM枚举(单选)
SET集合(多选)

冷知识:MySQL没有独立的布尔类型,用TINYINT(1)代替,0代表FALSE,1代表TRUE。但在某些ORM框架中,会自动将TINYINT(1)映射为布尔值。


数值类型

tinyint类型

有符号 vs 无符号
  • 有符号:范围-128~127(占1字节)
  • 无符号:范围0~255(同样占1字节)

实战案例
假设设计一个用户积分表:

CREATE TABLE user_points (
    user_id INT,
    points TINYINT UNSIGNED
);

如果积分上限为200,用TINYINT UNSIGNED足够;但若未来需要支持更高积分(如500),则必须改为SMALLINT UNSIGNED,否则插入500会报错。

为何慎用无符号?

无符号类型看似能节省空间,但可能埋下隐患:

  • 扩展性差:如年龄字段若用TINYINT UNSIGNED(0-255),当遇到异常值(如输入300)会直接报错,而有符号类型可临时存储负数用于标记异常。
  • 兼容性问题:某些编程语言或框架对无符号类型支持不佳,可能引发转换错误。

bit类型

位类型的高级应用

BIT类型适合存储开关状态或权限位掩码。例如,一个用户权限字段:

CREATE TABLE user_permissions (
    user_id INT,
    perms BIT(8) -- 每位代表一种权限
);

插入权限:

INSERT INTO user_permissions VALUES (1, b'00000011'); -- 同时有第1和第2位权限

通过位运算查询权限:

SELECT * FROM user_permissions WHERE perms & b'00000001'; -- 查找有第一位权限的用户
显示问题与解决方案

BIT类型显示时按ASCII码转换可能导致混乱。例如:

INSERT INTO user_permissions VALUES (2, 10); -- 10对应ASCII换行符

查询结果可能显示为空白或特殊字符。解决方案

  • 应用层处理:将BIT转换为整数或自定义字符串映射。
  • 使用INT代替BIT:对于不超过32位的权限,直接用INT存储更直观。

float类型

精度陷阱与四舍五入

FLOAT(M,D)的M是总位数,D是小数位数。例如FLOAT(4,2)存储范围是-99.99到99.99,但实际可插入范围是-99.994到99.994,超出时会四舍五入或报错。

CREATE TABLE measurements (
    val FLOAT(4,2)
);
INSERT INTO measurements VALUES (99.994); -- 存储为99.99
INSERT INTO measurements VALUES (99.995); -- 存储为100.0,触发报错
何时选择FLOAT vs DECIMAL?
  • FLOAT:适合科学计算,允许一定误差(如传感器数据)。
  • DECIMAL:金融场景必须使用,如存储账户余额,避免浮点误差。

decimal类型

精确计算的王者

DECIMAL的存储机制使其成为金融系统的首选。例如:

CREATE TABLE accounts (
    balance DECIMAL(10,2)
);

存储100.01时,DECIMAL确保精确到分,而FLOAT可能存储为100.009999。

存储开销对比
DECIMAL每4字节存9个数字,小数点单独占1字节。例如DECIMAL(10,2)占用5字节(9个数字+1字节小数点),而FLOAT固定占4字节。


字符串类型

char类型

定长存储的适用场景

CHAR(L)适用于长度固定的字符串,如身份证号(18位)、手机号(11位)。例如:

CREATE TABLE users (
    id_card CHAR(18)
);

插入不足18位时会自动补空格,查询时尾部空格被自动去除。

性能优势

  • 定长存储便于快速定位,适合频繁更新的字段。
  • 作为主键时,CHAR比VARCHAR更高效(如UUID)。

varchar类型

变长存储的灵活性

VARCHAR(L)适合长度波动大的字段,如用户名、地址。例如:

CREATE TABLE addresses (
    street VARCHAR(100)
);

存储"Main St"仅占用7字节(数据+1字节长度标识),而CHAR(100)会占用100字节。

编码对最大长度的影响

  • UTF8MB4下,VARCHAR(21844) ≈ 65532字节(21844 × 3字节/字符 + 2字节长度标识)
  • GBK下,VARCHAR(32766) ≈ 65532字节(32766 × 2字节/字符 + 2字节长度标识)

最佳实践

  • 定义表时显式指定字符集:CREATE TABLE example (...) CHARSET=utf8mb4;
  • 避免过度使用VARCHAR(255):根据实际数据长度选择合适值,节省空间并提高缓存效率。

char和varchar比较

特性CHARVARCHAR
空间占用固定L字符实际长度+1~2字节
速度快(定长)稍慢(需读长度)
适用场景身份证号、手机号名字、地址等变长字段

选择建议

  • 长度固定的字段(如MD5值)用CHAR
  • 长度波动大的字段(如文章内容)用VARCHAR

扩展案例
存储IP地址时,CHAR(15)(如"192.168.1.1")比VARCHAR更高效,因为IPv4地址固定为15字符以内。


时间日期类型

三大时间类型对比

类型格式占用空间特点
DATEYYYY-MM-DD3字节只存日期
DATETIMEYYYY-MM-DD HH:MM:SS8字节范围1000-9999年
TIMESTAMPYYYY-MM-DD HH:MM:SS4字节自动更新,默认当前时间

实战案例
设计评论表时,使用TIMESTAMP记录发布时间:

CREATE TABLE comments (
    id INT,
    content TEXT,
    create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

插入数据时无需指定create_time,自动填充当前时间。更新记录时,可设置TIMESTAMP自动更新:

ALTER TABLE comments ADD update_time TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;

时区问题

  • DATETIME不存储时区信息,显示依赖客户端设置。
  • TIMESTAMP存储UTC时间,查询时自动转换为当前时区。

enum和set类型

枚举类型(ENUM)

单选场景优化

ENUM适合选项固定的单选字段,如订单状态:

CREATE TABLE orders (
    status ENUM('pending', 'processing', 'shipped', 'canceled')
);

插入非枚举值会报错,确保数据一致性。

内部存储机制
ENUM存储为数字索引(1-based),如ENUM('a','b','c')中,a=1,b=2,c=3。可通过数字访问:

SELECT * FROM orders WHERE status = 3; -- 查找所有已取消订单

不推荐此方式,可读性差。


集合类型(SET)

多选场景优化

SET适合多选字段,如用户兴趣标签:

CREATE TABLE users (
    interests SET('sports', 'music', 'reading')
);

插入多选值:

INSERT INTO users VALUES ('sports,music');

位运算原理
SET用位图存储,每个选项对应一个二进制位:

  • sports = 1 (0b0001)
  • music = 2 (0b0010)
  • reading = 4 (0b0100)

查询包含"music"的用户:

SELECT * FROM users WHERE interests & 2;

局限性

  • 最多64个选项。
  • 修改枚举/集合列表需ALTER TABLE,不适合动态选项。

数据类型选择的技巧

1. 空间与性能的权衡

  • 数值类型:优先使用最小能满足需求的类型。例如,年龄字段用TINYINT而非INT。
  • 字符串类型:避免滥用VARCHAR(255),根据实际数据长度选择,减少内存占用。
  • 日期类型:若只需日期(如生日),用DATE而非DATETIME,节省5字节存储。

2. 金融场景的必杀技

涉及金额字段必须使用DECIMAL,避免FLOAT/DOUBLE的精度问题。例如:

CREATE TABLE transactions (
    amount DECIMAL(15,4) -- 精确到分,保留4位小数
);

3. JSON类型的应用

MySQL 5.7+支持JSON类型,适合存储半结构化数据:

CREATE TABLE settings (
    user_id INT,
    preferences JSON
);
INSERT INTO settings VALUES (1, '{"theme": "dark", "notifications": true}');

查询JSON字段:

SELECT * FROM settings WHERE JSON_EXTRACT(preferences, '$.theme') = 'dark';

常见误区与解决方案

误区1:盲目使用INT存储一切数值

  • 问题:用INT存储IP地址(如192.168.1.1转为3232235779),查询时需转换回字符串。
  • 解决方案:使用INET_ATON()和INET_NTOA()函数,或直接用CHAR(15)存储。

误区2:过度依赖ENUM/SET

  • 问题:ENUM选项频繁变动时需频繁执行ALTER TABLE。
  • 解决方案:用外键关联独立的状态表,如:
CREATE TABLE order_statuses (
    id TINYINT PRIMARY KEY,
    name VARCHAR(20)
);
CREATE TABLE orders (
    status_id TINYINT,
    FOREIGN KEY (status_id) REFERENCES order_statuses(id)
);

误区3:忽略字符集影响

  • 问题:VARCHAR(255)在UTF8MB4下占用255×4=1020字节,可能超过行大小限制(65535字节)。
  • 解决方案:合理规划字段长度,或使用TEXT/BLOB类型。

性能优化与最佳实践

1. 索引字段的选择

  • 优先选择短字段:如CHAR(2)的省份代码比VARCHAR(50)更适合索引。
  • 避免在TEXT/BLOB上创建全列索引:使用前缀索引,如INDEX (content(100))

2. 自增主键的陷阱

  • 问题:BIGINT占用8字节,若数据量不大可用INT UNSIGNED(上限42亿)。
  • 优化:中小型表使用INT即可,节省空间并提高缓存命中率。

3. 分区表的类型适配

  • 按时间分区:使用DATE/DATETIME字段,避免使用INT存储时间戳。
  • 按范围分区:确保分区键类型支持所需范围(如DECIMAL不适合作为分区键)。

4. 批量插入的类型优化

  • 问题:插入大量DECIMAL数据时,字符串转换可能成为瓶颈。
  • 优化:在应用层预处理为数值格式,或使用LOAD DATA INFILE。

个人建议

  1. 数值类型:优先INT/FLOAT,除非有特殊空间需求。
  2. 字符串:短文本用CHAR,长文本用VARCHAR。
  3. 时间:需要自动更新用TIMESTAMP,否则用DATETIME。
  4. 枚举:选项少且固定用ENUM,多选用SET。
  5. 避免陷阱
    • BIT类型慎用,显示容易混乱。
    • ENUM/SET用数字访问可读性差。
    • VARCHAR长度要根据编码计算实际字节。

最后提醒:数据类型选择直接影响性能和存储,设计表结构时务必结合业务场景仔细考量。例如,电商系统中商品ID用BIGINT,而内部系统用INT即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2395683.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

移动端 UI自动化测试学习之Appium框架(包含adb调试工具介绍)

文章目录 前言adb调试工具adb组成常用命令获取程序的包名和界面名文件传输发送文件到手机从手机中拉取文件 获取app启动时间获取手机日志其他命令 Appium 简介工作原理图 环境搭建安装客户端库(appium lib)安装Appium Server安装JDK(自行下载…

CS144 - Lecture 2

CS144 - Lecture 1 TCP 这里就简单讲了一下它的基本性质,没啥好说的 UDP 提供不可靠的传输服务,我们的 DNS 服务和 DHCP 都是用的 UDP 协议。 对于 DNS 我们只是单纯地向 DNS 服务器发送域名,然后返回一个 IP,如果还需要建立…

B站视频下载器 v1.0.4|免登录下载1080P视频

核心亮点 ✅ 无需登录下载1080P高清视频✅ 支持Windows/macOS双平台✅ 纯净无广告完全免费✅ 可单独下载视频/音频/弹幕/字幕/封面 三步极简操作 粘贴B站视频链接选择保存位置点击「开始下载」 特色功能 独立下载选项(视频/音频/弹幕/字幕/封面)登录…

AIGC学习笔记(8)——AI大模型开发工程师

文章目录 AI大模型开发工程师007 LangChain之Model IO模块1 Model IO核心概念2 Model IO代码实战什么是LCEL?ModelModel的分类LLMsChatModel PromptPrompt templatesExample selectorsOutput parsers AI大模型开发工程师 007 LangChain之Model IO模块 1 Model IO核…

[蓝桥杯]剪格子

剪格子 题目描述 如下图所示,3 x 3 的格子中填写了一些整数。 我们沿着图中的红色线剪开,得到两个部分,每个部分的数字和都是 60。 本题的要求就是请你编程判定:对给定的 mnmn 的格子中的整数,是否可以分割为两个部…

明远智睿SSD2351开发板:语音机器人领域的变革力量

在人工智能快速发展的今天,语音机器人逐渐成为人们生活和工作中的得力助手。明远智睿SSD2351开发板凭借强大性能与丰富功能,为语音机器人的发展注入新动力,成为该领域的变革力量。 SSD2351开发板的四核1.4GHz处理器具备强劲的运算性能&#x…

Co-IP—验证蛋白互作的不二之选

蛋白互作在细胞生命活动中起着至关重要的作用,并在不同的时空层面上参与多种细胞活动,因此研究蛋白互作对于理解分子调控网络至关重要。而在植物中筛选到潜在的互作蛋白后,大多数情况下,获得表达两种蛋白的稳定转化植株费时又费力…

数据可视化(第4、5、6次课)

Matplotlib 折线图 import numpy as np import matplotlib.pyplot as plt import matplotlib # 配置中文格式——保证图中出现中文的时候不会乱码 matplotlib.rcParams[font.sans-serif][SimHei] matplotlib.rcParams[axes.unicode_minus]False # 绘图 x np.linspace(0,2*np…

DAY 18 推断聚类后簇的类型

目录 DAY 18 推断聚类后簇的类型1.推断簇含义的2个思路:先选特征和后选特征2.通过可视化图形借助ai定义簇的含义3.科研逻辑闭环:通过精度判断特征工程价值作业:参考示例代码对心脏病数据集采取类似操作,并且评估特征工程后模型效果有无提升。…

结合源码分析Redis的内存回收和内存淘汰机制,LRU和LFU是如何进行计算的?

Redis 内存回收 1. 过期 key 处理 Redis 之所以性能强,最主要的原因就是基于内存存储。然而单节点的 Redis 其内存大小不宜过大,会影响持久化或主从同步性能。我们可以通过修改配置文件来设置Redis的最大内存: 当内存使用达到上限时&#…

ESG体系

文字来自腾讯元宝 ESG是什么? ESG体系是一套综合评估企业在环境(Environmental)、社会(Social)和治理(Governance) 三个维度表现的非财务绩效标准,旨在衡量企业可持续发展能力和长期…

华为深度学习面试手撕题:手写nn.Conv2d()函数

题目 只允许利用numpy包,实现Pytorch二维卷积函数nn.Conv2d() 解答 此代码考察二维卷积的概念,详见: 6.2. 图像卷积 — 动手学深度学习 2.0.0 documentation 6.3. 填充和步幅 — 动手学深度学习 2.0.0 documentation 6.4. 多输入多输出通…

归一化相关

归一化相关问题 归一化方式Batch NormalizationLayer NormalizationInstance NormalizationGroup NormalizationRMSNorm(Root Mean Square Layer Normalization):RMSNorm 和 LayerNorm区别?归一化方式 Batch Normalization 在每一层的输入进行归一化处理,使其在每个批次内…

Git深入解析功能逻辑与核心业务场景流程

一、Git核心功能逻辑架构 #mermaid-svg-9tj1iCr99u6QenJM {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-9tj1iCr99u6QenJM .error-icon{fill:#552222;}#mermaid-svg-9tj1iCr99u6QenJM .error-text{fill:#552222;st…

LINUX528 重定向

2>&1 我的理解: 2>&1,2stderr错误输出,1stdout输出,stderr一般和stdout是分别输出(管道符只传递stdout,据元宝,stderr默认输出到终端;如果重定向符不进行2显示重定向&…

研华工控机安装Windows10系统,适用UEFI(GPT)格式安装

主要硬件 主板:AIMB-787 、CPU:i5-6500 U盘启动工具:通过网盘分享的文件:rufus-3.20.zip 链接: https://pan.baidu.com/s/1YlFfd-_EhFHCG4sEHBQ8dQ?pwdQT12 提取码: QT12 Win10 22H2 Pro 纯净版系统:通过网盘分享…

1、树莓派更换软件下载源

树莓派官方系统raspbian自带的是国外的软件源,在国内使用经常会遇到无法下载软件的问题。 以下是把raspbian系统(buster版本)的下载源改为阿里云软件源的方法。 1、修改sources.list文件 sudo nano /etc/apt/sources.list 将初始化中的代…

历年中山大学计算机保研上机真题

历年中山大学计算机保研上机真题 2025中山大学计算机保研上机真题 2024中山大学计算机保研上机真题 2023中山大学计算机保研上机真题 在线测评链接:https://pgcode.cn/school 不连续1的子串 题目描述 给定一个数字 n n n,输出长度为 n n n 的 01…

Python----目标检测(《SSD: Single Shot MultiBox Detector》论文和SSD的原理与网络结构)

一、SSD:单次多框检测器 1.1、基本信息 标题:SSD: Single Shot MultiBox Detector 作者:Wei Liu (UNC Chapel Hill), Dragomir Anguelov (Zoox Inc.), Dumitru Erhan, Christian Szegedy (Google Inc.), Scott Reed (University of Michiga…

springboot集成websocket给前端推送消息

一般通常情况下,我们都是前端主动朝后端发送请求,那么有没有可能,后端主动给前端推送消息呢?这时候就可以借助websocket来实现。下面给出一个简单的实现样例。 首先创建一个websocketDemo工程,该工程的整体结构如下&a…