【MySQL数据库基础】(五)MySQL 数据类型深度解析:选对类型 = 性能拉满!

【MySQL数据库基础】(五)MySQL 数据类型深度解析:选对类型 = 性能拉满!

前言

        在 MySQL 表结构设计中,数据类型的选择是最核心也最容易踩坑的环节。很多开发者随手给字段设为intvarchar(255),看似省事,实则会导致磁盘空间浪费、查询效率低下,甚至出现数据溢出、精度丢失的问题。

        选对数据类型的本质,是用最小的存储空间存储符合业务需求的数据,这不仅能节省服务器资源,还能提升索引和查询的效率。本文将从 MySQL 的四大核心数据类型(数值、字符串、日期时间、枚举集合)出发,结合实战案例讲透每种类型的用法、边界、坑点,还有不同场景下的选择技巧,让你从根源上做好表结构设计!下面就让我们正式开始吧!

一、数据类型总览:四大类覆盖所有业务场景

        MySQL 提供了丰富的数据类型,按用途可分为数值类型字符串类型日期时间类型特殊字符串类型(ENUM/SET),不同类型对应不同的存储规则和业务场景,核心设计原则是按需选择,宁小勿大

        先看一张核心数据类型分类表,快速建立整体认知:

分类核心类型适用场景
数值类型TINYINT/INT/BIGINT/FLOAT/DECIMAL年龄、ID、金额、计数等
字符串类型CHAR/VARCHAR/TEXT/BLOB姓名、手机号、地址、大文本等
日期时间类型DATE/DATETIME/TIMESTAMP生日、创建时间、时间戳等
特殊字符串类型ENUM/SET性别(单选)、爱好(多选)等

        接下来我们逐个拆解,结合实战案例讲透每种类型的使用细节。

二、数值类型:精准控制范围和精度,拒绝浪费空间

        数值类型是开发中最常用的类型,分为整型位类型浮点 / 定点型,核心要点是根据数据范围选择最小的类型,避免用BIGINT存年龄、用INT存手机号这类低级错误。

2.1 整型:从 TINYINT 到 BIGINT,按需选择

        MySQL 的整型支持有符号(SIGNED)和无符号(UNSIGNED),默认有符号,可通过UNSIGNED关键字指定无符号,不同整型的字节数和范围差异巨大,直接决定了存储空间和数据边界。

        核心整型参数表(必背):

实战坑点:整型越界问题

        MySQL 对整型做了严格的范围校验,插入超出范围的数据会直接报错,这是新手最容易遇到的问题。

-- 创表:用TINYINT存年龄(有符号,范围-128~127) create table t_int(num tinyint); -- 插入正常数据:成功 insert into t_int values(20); -- 插入越界数据:直接报错(ERROR 1264: Out of range) insert into t_int values(128); 

关键建议:尽量不用 UNSIGNED

        很多人会用UNSIGNED扩大整型范围,比如TINYINT UNSIGNED存 0~255 的数,但官方更建议提升整型类型而非用 UNSIGNED—— 比如INT存不下的数据,INT UNSIGNED也大概率存不下,不如直接用BIGINT,避免无符号带来的查询和计算问题。

2.2 BIT 类型:按位存储,极致节省空间

    BIT(M)是位类型,M表示位数,范围 1~64,默认 1,仅用于存储 0/1 或少量二进制数,是最节省空间的数值类型。

核心用法和坑点

-- 创表:BIT(8)表示8位,BIT(1)仅存0/1(比如性别) create table t_bit(gender bit(1), num bit(8)); -- 插入正常数据:0/1符合BIT(1)范围,成功 insert into t_bit values(0, 65); -- 插入越界数据:BIT(1)只能存0/1,插入2直接报错 insert into t_bit values(2, 65); -- 查询结果:BIT字段按ASCII码显示(65对应字符A) select * from t_bit; -- 结果:gender=NULL,num=A 

        适用场景:仅用于存储二值状态(0/1),比如性别、是否删除、是否启用,用BIT(1)TINYINT更节省空间。

2.3 浮点 / 定点型:处理小数,精度是关键

        用于存储小数的类型有FLOATDOUBLE(浮点型)和DECIMAL(定点型),核心差异是精度:浮点型精度低,会有舍入误差;定点型精度高,适合存储金额等对精度要求高的数据。

2.3.1 FLOAT/DOUBLE:浮点型,适合非高精度场景

        语法:FLOAT(M,D) [UNSIGNED]M表示总长度,D表示小数位数,FLOAT占 4 字节,DOUBLE占 8 字节,MySQL 会自动对数据四舍五入

-- 创表:FLOAT(4,2)表示总长度4,小数2位,范围-99.99~99.99 create table t_float(salary float(4,2)); -- 插入正常数据:成功 insert into t_float values(99.99); -- 插入带尾数数据:自动四舍五入为99.99 insert into t_float values(99.994); -- 插入越界数据:报错 insert into t_float values(100.00); 

        适用场景:身高、体重、温度等对精度要求不高的小数场景。

2.3.2 DECIMAL:定点型,金融场景必选

        语法:DECIMAL(M,D) [UNSIGNED]M表示总长度(最大 65),D表示小数位数(最大 30),无舍入误差,精度 100%,是金额、汇率等金融场景的唯一选择。

浮点型 vs 定点型:精度对比实战

-- 创表:对比FLOAT(10,8)和DECIMAL(10,8)的精度 create table t_decimal(s1 float(10,8), s2 decimal(10,8)); -- 插入相同的高精度小数 insert into t_decimal values(23.12345612, 23.12345612); -- 查询结果:FLOAT出现舍入误差,DECIMAL精准保留 select * from t_decimal; -- 结果:s1=23.12345695,s2=23.12345612 

        核心结论所有涉及金额的字段,一律用 DECIMAL,杜绝浮点误差导致的业务问题。

三、字符串类型:CHAR 和 VARCHAR 的终极选择指南

        字符串类型是最灵活也最容易用错的类型,核心是 CHAR(固定长度)和VARCHAR(可变长度)的选择,还有大文本场景的TEXT类型,用错会直接导致空间浪费或查询效率暴跌。

3.1 CHAR:固定长度字符串,高效但费空间

        语法:CHAR(L)L表示字符数,最大 255,无论实际存储多少字符,都会占用L个字符的存储空间,超出长度直接报错。

-- 创表:CHAR(2)表示存2个字符(字母/汉字均可) create table t_char(name char(2)); -- 插入正常数据:字母、汉字都支持,成功 insert into t_char values('ab'),('中国'); -- 插入越界数据:3个字符,报错 insert into t_char values('abc'); -- 插入1个字符:仍占用2个字符空间,自动补空格 insert into t_char values('a'); 

        特点:查询效率高(无需计算实际长度),但会浪费空间,适合存储长度固定的字符串。

3.2 VARCHAR:可变长度字符串,省空间但稍慢

        语法:VARCHAR(L)L表示字符数,最大长度和编码相关,实际占用空间为实际字符数 + 1~3 字节(用于记录数据长度),是开发中最常用的字符串类型。

关键知识点:VARCHAR 的长度限制

        VARCHAR 的最大有效字节数是 65532(预留 3 字节存长度),因此L的最大值和表的字符编码强相关:

UTF8 编码(1 字符 = 3 字节):L最大 = 65532/3=21844GBK 编码(1 字符 = 2 字节):L最大 = 65532/2=32766

        超出这个范围会直接报错,实战验证:

-- UTF8编码下,创建VARCHAR(21845):报错(Row size too large) create table t_varchar1(name varchar(21845)) charset=utf8; -- UTF8编码下,创建VARCHAR(21844):成功 create table t_varchar2(name varchar(21844)) charset=utf8; 

3.3 CHAR 和 VARCHAR:对比与选择原则

        这是面试和开发中的高频问题,核心看数据长度是否固定,用一张表讲透差异:

特性CHAR(4)VARCHAR(4)
存储规则固定 4 个字符,补空格实际字符数 + 1 字节
占用空间浪费(比如存 1 个字符也占 4 个)节省(按需分配)
查询效率高(无需计算长度)稍低(需解析长度)
最大长度255 字符随编码变化(UTF8=21844)

终极选择原则(背下来!)

用 CHAR:数据长度固定,比如手机号(11 位)、身份证号(18 位)、MD5 值(32 位)、状态码(固定字符);用 VARCHAR:数据长度不固定,比如姓名、地址、商品名称、描述等;禁止用 VARCHAR (255):除非确定数据最大长度是 255,否则按实际业务需求设值(比如姓名设VARCHAR(20),地址设VARCHAR(100)),避免浪费空间和索引效率下降。

3.4 TEXT/BLOB:大文本 / 二进制类型,慎用

        当字符串长度超过 VARCHAR 的限制时,用TEXT(大文本)或BLOB(二进制),但慎用这两个类型

TEXT:存储大文本,比如文章内容、评论,不支持全文索引,不支持默认值;BLOB:存储二进制数据,比如图片、文件,不建议在 MySQL 中存储大文件,优先用文件服务器(比如 OSS)。

        核心建议:尽量避免在表中使用TEXT/BLOB,会导致表的查询效率大幅下降,如需存储,建议单独建表关联。

四、日期时间类型:DATE/DATETIME/TIMESTAMP

        日期时间类型用于存储时间相关数据,核心是DATE(日期)DATETIME(日期时间)TIMESTAMP(时间戳),三者的存储大小、范围、自动更新特性差异巨大,选对能让时间操作更便捷。

4.1 三大日期类型核心参数

类型字节数格式时间范围自动更新时区依赖
DATE3yyyy-mm-dd1000-01-01 ~ 9999-12-31
DATETIME8yyyy-mm-dd hh:mm:ss1000-01-01 ~ 9999-12-31
TIMESTAMP4yyyy-mm-dd hh:mm:ss1970-01-01 ~ 2038-01-19

4.2 实战演示:TIMESTAMP 的自动更新特性

    TIMESTAMP是开发中最常用的类型,核心特性是自动赋值 / 更新—— 插入数据时自动设为当前时间,更新数据时自动刷新为当前时间,无需手动操作,适合做创建时间 / 更新时间

-- 创表:DATE(生日)、DATETIME(自定义时间)、TIMESTAMP(自动时间) create table t_time(t1 date, t2 datetime, t3 timestamp); -- 插入数据:仅给t1、t2赋值,t3自动设为当前时间 insert into t_time(t1,t2) values('1999-01-01','2024-01-01 12:00:00'); -- 查询结果:t3显示当前插入时间 select * from t_time; -- 更新数据:仅修改t1,t3自动刷新为当前更新时间 update t_time set t1='2000-01-01'; -- 查询结果:t3变为最新时间 select * from t_time; 

4.3 选择原则

存仅日期:比如生日、入职日期,用DATE存自定义时间且范围大:比如订单创建时间(需长期保存),用DATETIME存自动更新的时间:比如数据最后修改时间,用TIMESTAMP(注意 2038 年范围限制);禁止用字符串存时间:很多人用 VARCHAR 存时间,会导致无法使用时间函数(比如 DATE_ADD、YEAR),查询和排序效率极低。

五、特殊字符串类型:ENUM(单选)和 SET(多选),简化业务开发

        MySQL 提供了ENUM(枚举)和SET(集合)两种特殊字符串类型,分别用于单选多选场景,比用 VARCHAR 存字符串更高效,还能做精准的条件查询,适合处理性别、爱好、分类等固定选项的业务场景。

5.1 ENUM:枚举类型,单选必选

        语法:ENUM('选项1','选项2','选项3',...)最多支持 65535 个选项,实际存储的是数字(1、2、3...),但显示为字符串,适合只能选一个的场景(比如性别、订单状态)。

-- 创表:gender为ENUM枚举,只能选男/女 create table t_enum(username varchar(20), gender enum('男','女')); -- 插入数据:直接插字符串,成功 insert into t_enum values('张三','男'),('李四','女'); -- 插入非法选项:报错(不在枚举范围内) insert into t_enum values('王五','未知'); -- 查询:可用数字代替枚举值(1=男,2=女) select * from t_enum where gender=1; 

5.2 SET:集合类型,多选必选

        语法:SET('选项1','选项2','选项3',...)最多支持 64 个选项,实际存储的是二进制数字,适合可以选多个的场景(比如爱好、标签),多个选项用逗号分隔,且选项本身不能包含逗号。

实战:爱好多选查询(核心坑点解决)

-- 创表:hobby为SET集合(登山/游泳/篮球/武术),gender为ENUM枚举 create table t_set( username varchar(20), hobby set('登山','游泳','篮球','武术'), gender enum('男','女') ); -- 插入数据:单选/多选都支持,多个爱好用逗号分隔 insert into t_set values ('雷锋','登山,武术','男'), ('李雷','登山','男'), ('韩梅梅','游泳','女'); -- 坑点:直接用=查询,只能查出仅选登山的记录,查不到多选包含登山的 select * from t_set where hobby='登山'; -- 仅返回李雷 -- 正确用法:用find_in_set()函数,查询包含登山的所有记录 select * from t_set where find_in_set('登山', hobby); -- 返回雷锋、李雷 

        find_in_set 函数find_in_set(子串, 逗号分隔的字符串),子串存在则返回下标,不存在返回 0,是 SET 集合查询的核心函数。

5.3 核心优势

效率更高:实际存储为数字,比 VARCHAR 存字符串更节省空间,查询速度更快;数据规范:限制了可选值,避免插入非法数据(比如性别插入 “未知”);查询便捷:通过数字或函数即可精准查询,无需模糊匹配。

六、MySQL 数据类型选择的黄金法则(避坑 99%)

        掌握了每种类型的用法后,总结了6 条黄金法则,无论是新手还是老开发,照做就能避开 99% 的坑,让表结构设计更合理、性能更优:

法则 1:宁小勿大,按需选择

        用最小的类型存储符合业务需求的数据,比如年龄用TINYINT而非INT,姓名用VARCHAR(20)而非VARCHAR(255),存储空间越小,索引和查询效率越高。

法则 2:优先使用原生类型

        禁止用字符串存储数值、时间、枚举 —— 比如用 VARCHAR 存手机号、用 VARCHAR 存时间、用 VARCHAR 存性别,会导致无法使用原生函数,查询和排序效率暴跌,还容易出现数据不一致。

法则 3:金额必用 DECIMAL,杜绝浮点误差

        所有金融相关的字段(金额、汇率、单价),一律用DECIMAL(M,D),不要用FLOAT/DOUBLE,避免舍入误差导致的业务问题(比如转账时少一分钱)。

法则 4:CHAR 和 VARCHAR 的选择看长度是否固定

        长度固定用 CHAR(比如手机号、身份证),长度不固定用 VARCHAR(比如姓名、地址),禁止无脑用VARCHAR(255)

法则 5:慎用 TEXT/BLOB,大文件放文件服务器

        尽量避免在表中使用TEXT/BLOB,会导致表查询效率下降;如需存储大文本,单独建表关联;图片、视频、文件等大二进制数据,优先用 OSS、FastDFS 等文件服务器,不要存在 MySQL 中。

法则 6:TIMESTAMP 做自动更新时间,注意范围限制

        用TIMESTAMP做数据的最后修改时间,利用其自动更新特性,简化开发;但注意其时间范围是 1970~2038,超出范围需用DATETIME


总结

        MySQL 数据类型的选择,本质是对业务需求的理解对存储规则的掌握。一张设计合理的表,其数据类型必然是 “刚刚好” 的 —— 既不会出现数据溢出、精度丢失,也不会浪费磁盘空间和查询效率。

        数据类型是 MySQL 的基础,也是表结构设计的第一步,选对了数据类型,后续的索引优化、查询优化才能事半功倍。希望这篇文章能让你彻底搞懂 MySQL 数据类型,从此告别表结构设计的坑!

        下一篇我们将讲解 MySQL数据的增删改查(CRUD),这是开发中最核心的业务操作,搭配实战案例让你快速上手,关注我,一起从 MySQL 入门到实战!

Read more

华为OD机试双机位C卷 - Alice的安全旅行 (C++ & JAVA & Python & C语言 & JS & GO)

华为OD机试双机位C卷 - Alice的安全旅行 (C++ & JAVA & Python & C语言 & JS & GO)

Alice的安全旅行 华为OD机试双机位C卷 - 华为OD上机考试双机位C卷 200分题型 华为OD机试双机位C卷真题目录点击查看: 华为OD机试双机位C卷真题题库目录|机考题库 + 算法考点详解 题目描述 Alice计划从城市0出发最终到达城市N-1,他可以选择一条路线,但路上经过的城市总数(包括起点和终点)不能超过K个,每个城市都有一个安全度值,整个旅程的安全度被定义为路径上所有城市安全度的最小值,她的目标是让这个最小值尽可能高,请问Alice的旅程总体安全度最大能为多少? 输入描述 第一行有两个整数N和K,表示一共N个城市,以及Alice最多去K个城市(2<N<100000,1<K<100000) 接下来N行 每行包括一个整数h 表示去某个城市的安全度0=<h<=1000000000 接下来一行有一个整数M,表示城市间的M条道路,0<M<200000 接下来M行 每行有两个整数s0 s1

By Ne0inhk
C++之基于正倒排索引的Boost搜索引擎项目usuallytool部分代码及详解

C++之基于正倒排索引的Boost搜索引擎项目usuallytool部分代码及详解

这部分是通用工具部分的代码,简单来说就是这份代码里面的函数会在项目的其他多个部分里面被使用,所以我们专门创建一个部分用来存储这些代码。 1.FileUtil 这个类就是专门用来读取文件用的,这个代码从指定的文件路径读取文件内容,将读取到的内容(按行读取)追加到传入的字符串指针(out)所指向的字符串中;同时,该方法会返回一个布尔值,用于标识读取操作是否成功 —— 若文件成功打开并完成读取,返回 true;若文件打开失败(如路径错误等),则输出错误信息并返回 false。 文件以二进制输入模式打开,读取过程中不会修改原文件内容。 class FileUtil{ public: static bool ReadFile(const std::string &file_path,std::string *out) { //下面这行代码就是在打开文件,并通过ifstream定义一个对象in,用于关联特定的文件 std::ifstream in(file_path,std::ios::in

By Ne0inhk
计算机毕设Java基于mvc的酒店管理系统 基于SSM框架的酒店客房预订与运营管理系统 Java Web驱动的智能化民宿服务管理平台

计算机毕设Java基于mvc的酒店管理系统 基于SSM框架的酒店客房预订与运营管理系统 Java Web驱动的智能化民宿服务管理平台

计算机毕设Java基于mvc的酒店管理系统58s0e9 (配套有源码 程序 mysql数据库 论文) 本套源码可以在文本联xi,先看具体系统功能演示视频领取,可分享源码参考。 随着旅游业的蓬勃发展和消费升级趋势的持续深化,酒店行业正经历着从传统人工管理模式向数字化、智能化运营的重要转型期。当前多数中小型酒店仍依赖手工登记、纸质档案和分散式信息处理,导致客房资源调配效率低下、客户信息碎片化、财务结算易出错等问题日益凸显。在"互联网+"时代背景下,构建一套集成客房资源管理、客户信息维护、预订入住一体化流程的信息化系统,已成为提升酒店服务响应速度、降低运营成本、增强市场竞争力的关键路径。本系统采用Java作为核心开发语言,基于MVC分层架构模式,结合SSM(Spring+Spring MVC+MyBatis)主流技术栈与MySQL关系型数据库,旨在打造一款轻量级、易部署、高扩展的酒店业务管理解决方案,适用于中小型酒店及连锁民宿的日常运营管理场景。 本系统采用前后端分离的双端架构设计,面向不同角色提供差异化的功能入口与服务能力。 * 首页信息聚合展示,包含系统简介与快捷导航入口 *

By Ne0inhk
【C++开源库使用】调用开源库STB中的stbi_load_from_memory加载图片文件,进行灰化处理,然后调用stbi_write_png或stbi_write_jpg将灰化图片保存到文件中

【C++开源库使用】调用开源库STB中的stbi_load_from_memory加载图片文件,进行灰化处理,然后调用stbi_write_png或stbi_write_jpg将灰化图片保存到文件中

目录 1、图片灰化的实现思路 2、开源STB库下载 3、将图片文件的内容读到buffer中 4、将buffer中存放的图片文件数据传入到stbi_load_from_memory接口中,然后对返回的图片颜色值进行灰化处理 5、调用stbi_write_png或stbi_write_jpg接口将灰化后的图片数据保存成图片文件 6、图片灰化的完整代码        前一篇文章我们讲到了使用libcurl库发http/https请求去下载用户头像文件(文章链接:https://blog.ZEEKLOG.net/chenlycly/article/details/149175549),本篇文章则是同个SDK项目的后续需求中涉及到的功能。第三方厂商要求,对于不在线的人员,要显示灰化的头像。经研究决定使用开源STB库辅助实现图片灰化,调用STB开源库中的stbi_load_from_memory、stbi_write_png或stbi_write_jpg等接口。本文详细讲述一下实现过程,以供大家借鉴或参考。

By Ne0inhk