04.MySQL数据类型详解

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.pswp.cn/bicheng/83300.shtml

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

相关文章

Spring AI 之对话记忆(Chat Memory)

大型语言模型(LLMs)是无状态的,这意味着它们不会保留关于之前交互的信息。当想在多次交互中保持上下文或状态时,这可能会成为一个限制。为了解决这一问题,Spring AI 提供了对话记忆功能,允许你在与大型语言…

Hölder Statistical Pseudo Divergence Proper Hölder Divergence

目录 Hlder Statistical Pseudo DivergenceProper Hlder Divergence Hlder Statistical Pseudo Divergence Hlder Statistical Pseudo Divergence是一种度量两个概率分布 p p p 和 q q q差异的方法,它基于Hlder不等式。定义如下: D α H ( p : q ) 1 …

时序数据库IoTDB基于云原生的创新与实践

概述 Apache IoTDB 是一款独立自研的物联网时序数据库,作为 Apache 基金会的顶级项目,它融合了产学研的优势,拥有深厚的科研基底。IoTDB 采用了端边云协同的架构,专为物联网设计,致力于提供极致的性能。 数据模型 I…

git 如何解决分支合并冲突(VS code可视化解决+gitLab网页解决)

1、定义:两个分支修改了同一文件的同一行代码,无法自动决定如何合并代码,需要人工干预的情况。(假设A提交了文件a,此时B在未拉取代码的情况下,直接提交是会报错的,此时需要拉取之后再提交才会成功&#xff…

系统架构设计师(一):计算机系统基础知识

系统架构设计师(一):计算机系统基础知识 引言计算机系统概述计算机硬件处理器处理器指令集常见处理器 存储器总线总线性能指标总线分类按照总线在计算机中所处的位置划分按照连接方式分类按照功能分类 接口接口分类 计算机软件文件系统文件类…

聊一聊接口测试中缓存处理策略

目录 一、强制绕过缓存 添加时间戳参数 修改请求头 二、主动清除缓存 清除本地缓存 清除服务端缓存(需权限) 清除CDN缓存 三、测试缓存逻辑 首次请求获取数据 记录响应头中的缓存标识​​​​​ 验证缓存生效 测试缓存过期​​​​​​​ 四…

机器学习算法-逻辑回归

今天我们用 「预测考试是否及格」 的例子来讲解逻辑回归,从原理到实现一步步拆解,保证零基础也能懂! 🎯 例子背景 假设你是班主任,要根据学生的「学习时间」预测「是否及格」,手上有以下数据:…

【论文解读】CVPR2023 PoseFormerV2:3D人体姿态估计(附论文地址)

论文链接:https://arxiv.org/pdf/2303.17472 源码链接:https://github.com/QitaoZhao/PoseFormerV2 Abstract 本文提出了 PoseFormerV2,通过探索频率域来提高 3D 人体姿态估计的效率和鲁棒性。PoseFormerV2 利用离散余弦变换(DC…

DRW - 加密市场预测

1.数据集描述 在本次比赛中,数据集包含加密市场的分钟级历史数据。您的挑战是预测未来的加密货币市场价格走势。这是一项kaggle社区预测竞赛,您可以以 CSV 文件的形式或通过 Kaggle Notebooks 提交您的预测。有关使用 Kaggle Notebooks 的更多详细信息&a…

嵌入式Linux系统中的启动分区架构

在嵌入式Linux系统架构中,Linux内核、设备树(Device Tree)与引导配置文件构成了系统启动的基础核心。如何安全、高效地管理这些关键文件,直接影响到系统的稳定性与可维护性。近年来,越来越多的嵌入式Linux开发者选择将启动相关文件从传统的“混合存放”方式,转向采用独立…

用户资产化视角下开源AI智能名片链动2+1模式S2B2C商城小程序的应用研究

摘要:在数字化时代,平台流量用户尚未完全转化为企业的数字资产,唯有将其沉淀至私域流量池并实现可控、随时触达,方能成为企业重要的数字资产。本文从用户资产化视角出发,探讨开源AI智能名片链动21模式S2B2C商城小程序在…

Spring是如何实现属性占位符解析

Spring属性占位符解析 核心实现思路1️⃣ 定义占位符处理器类2️⃣ 处理 BeanDefinition 中的属性3️⃣ 替换具体的占位符4️⃣ 加载配置文件5️⃣ Getter / Setter 方法 源码见:mini-spring 在使用 Spring 框架开发过程中,为了实现配置的灵活性&#xf…

【大模型面试每日一题】Day 31:LoRA微调方法中低秩矩阵的秩r如何选取?

【大模型面试每日一题】Day 31:LoRA微调方法中低秩矩阵的秩r如何选取? 📌 题目重现 🌟🌟 面试官:LoRA微调方法中低秩矩阵的秩r如何选取?: #mermaid-svg-g5hxSxV8epzWyP98 {font-family:"…

字节golang后端二面

前端接口使用restful格式,post与get的区别是什么? HTTP网络返回的状态码有哪些? go语言切片与数组的区别是什么? MySQL实现并发安全避免两个事务同时对一个记录写操作的手段有哪些? 如何实现业务的幂等性(在…

Spring Security安全实践指南

安全性的核心价值 用户视角的数据敏感性认知 从终端用户角度出发,每个应用程序都涉及不同级别的数据敏感度。以电子邮件服务与网上银行为例:前者内容泄露可能仅造成隐私困扰,而后者账户若被操控将直接导致财产损失。这种差异体现了安全防护需要分级实施的基本原则: // 伪…

Leetcode第451场周赛分析总结

题目链接 竞赛 - 力扣&#xff08;LeetCode&#xff09;全球极客挚爱的技术成长平台 题目解析 A. 3560. 木材运输的最小成本 AC代码 class Solution { public:long long minCuttingCost(int n, int m, int k) {if (n > m) swap(n, m); // n < m;using ll long lon…

Linux中的shell脚本

什么是shell脚本 shell脚本是文本的一种shell脚本是可以运行的文本shell脚本的内容是由逻辑和数据组成shell脚本是解释型语言 用file命令可以查看文件是否是一个脚本文件 file filename 脚本书写规范 注释 单行注释 使用#号来进行单行注释 多行注释 使用 : " 注释内容…

PHP与MYSQL结合中中的一些常用函数,HTTP协议定义,PHP进行文件编程,会话技术

MYSQL&#xff1a; 查询函数: 执行查询语句: 1.mysql_query("SQL语法"); 凡是执行操作希望拿到数据库返回的数据进行展示的(结果返回: 数据结果); 2.执行结果的处理:成功为结果集&#xff0c;失败为false; 成功返回结果:SQL指令没有错误&#xff0c;但是查询结果…

数学分析——一致性(均匀性)和收敛

目录 1. 连续函数 1.1 连续函数的定义 1.2 连续函数的性质 1.2.1 性质一 1.2.2 性质二 1.2.3 性质三 1.2.4 性质四 2. 一致连续函数 2.1 一致连续函数的定义 2.2 一致连续性定理(小间距定理)(一致连续函数的另一种定义) 2.3 一致连续性判定法 2.4 连…

湖北理元理律师事务所:企业债务优化的科学路径与人文关怀

湖北理元理律师事务所&#xff1a;企业债务优化的科学路径与人文关怀 在中小企业经营压力增大的背景下&#xff0c;如何平衡债务清偿与员工生计成为关键课题。湖北理元理律师事务所联合计划集团公司&#xff0c;为服务企业设计了一套兼顾法律合规性与民生保障的债务解决方案&a…