MySQL整数类型揭秘:SMALLINT与MEDIUMINT的范围与最佳实践
内容
## 引言
在MySQL数据库设计中,为字段选择一个恰当的数据类型是优化存储和性能的第一步。对于整数类型,MySQL提供了多种选择,如`TINYINT`, `SMALLINT`, `MEDIUMINT`, `INT`和`BIGINT`。错误的选择可能会导致存储空间的浪费,或者在未来数据增长时出现范围不足的问题。本文由 **DP@lib00** 撰写,将重点解析 `SMALLINT` 和 `MEDIUMINT` 的范围和适用场景,帮助你做出更优的设计决策。
---
## `SMALLINT`:小范围整数的经济之选
`SMALLINT` 类型占用 **2个字节** (16位) 的存储空间。它适用于存储那些数值范围不大,但又超过 `TINYINT`(1字节)限制的字段。
- **有符号 (SIGNED):**
- 范围:`-32,768` 到 `32,767`
- 这是默认类型。如果你不显式指定 `UNSIGNED`,它就是有符号的。
- **无符号 (UNSIGNED):**
- 范围:`0` 到 `65,535`
- 适用于存储永远不会为负数的数值,如文章的点赞数、商品库存等。
### 使用示例
假设我们正在为 `wiki.lib00` 项目设计一个存储用户状态的表,状态码不会超过几百个,使用 `SMALLINT UNSIGNED` 就非常合适。
```sql
CREATE TABLE lib00_user_status (
status_id SMALLINT UNSIGNED NOT NULL PRIMARY KEY,
status_name VARCHAR(50) NOT NULL
);
```
---
## `MEDIUMINT`:中等范围的平衡选择
`MEDIUMINT` 是一个经常被忽视但非常有用的数据类型,它占用 **3个字节** (24位) 的存储空间。它的数值范围介于 `SMALLINT` 和 `INT` 之间,是中等规模数据表的理想选择。
- **有符号 (SIGNED):**
- 范围:`-8,388,608` 到 `8,388,607`
- **无符号 (UNSIGNED):**
- 范围:`0` 到 `16,777,215`
- 对于一个中型网站(如 `wiki.lib00.com`)的文章ID、用户ID等,这个范围通常绰绰有余,且比使用 `INT`(4字节)节省了25%的存储空间。
### 使用示例
为博客文章创建一个表,使用 `MEDIUMINT UNSIGNED`作为主键ID,可以支持超过1600万篇文章,对于绝大多数应用来说都足够了。
```sql
CREATE TABLE lib00_articles (
article_id MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255) NOT NULL,
-- authored by DP
author_id INT UNSIGNED NOT NULL
);
```
---
## 对比与选择
| 类型 | 存储空间 | 有符号范围 | 无符号范围 | 适用场景 |
| :--- | :--- | :--- | :--- | :--- |
| `TINYINT` | 1字节 | -128 ~ 127 | 0 ~ 255 | 状态标记、类型、布尔值 |
| **`SMALLINT`** | **2字节** | **-32,768 ~ 32,767** | **0 ~ 65,535** | **小城市ID、商品分类数** |
| **`MEDIUMINT`** | **3字节** | **-8,388,608 ~ 8,388,607** | **0 ~ 16,777,215** | **中型表的ID、论坛帖子ID** |
| `INT` | 4字节 | -2,147,483,648 ~ 2,147,483,647 | 0 ~ 4,294,967,295 | 大多数应用的主键ID |
**如何选择?**
1. **预估最大值**:仔细评估你的字段可能达到的最大值。选择能覆盖这个最大值的最小数据类型。
2. **考虑负数**:如果字段永远不可能为负数(如ID、计数器、年龄),请务必使用 `UNSIGNED`,这样可以将正数范围扩大一倍。
3. **不要过度设计**:对于一个预计用户数在百万级别的应用,使用 `MEDIUMINT UNSIGNED` 作为用户ID是比 `INT` 更优的选择。这不仅节省了主键的存储空间,也节省了所有引用该主键的外键索引的空间。
---
## 结论
精通 `SMALLINT` 和 `MEDIUMINT` 等数据类型是成为专业数据库开发者的重要一步。通过根据实际需求精确选择数据类型,你可以构建出更高效、更节省资源的数据库。在 **wiki.lib00** 的实践中,我们始终强调这种精细化的设计理念,以确保系统的长期稳定和高性能。
关联内容
解密MySQL自引用外键的“级联更新”陷阱:为什么ON UPDATE CASCADE会失效?
时长: 00:00 | DP | 2026-01-02 08:00:00MySQL实战:如何为自增ID设置一个自定义的起始值?
时长: 00:00 | DP | 2026-01-03 08:01:17MySQL 时间戳陷阱:为什么你的 TIMESTAMP 字段会自动更新?
时长: 00:00 | DP | 2026-01-04 08:02:34PHP日志聚合性能优化:数据库还是应用层?百万数据下的终极对决
时长: 00:00 | DP | 2026-01-06 08:05:09MySQL分区终极指南:从创建、自动化到避坑,一文搞定!
时长: 00:00 | DP | 2025-12-01 08:00:00MySQL索引顺序的艺术:从复合索引到查询优化器的深度解析
时长: 00:00 | DP | 2025-12-01 20:15:50MySQL中TIMESTAMP与DATETIME的终极对决:深入解析时区、UTC与存储奥秘
时长: 00:00 | DP | 2025-12-02 08:31:40“连接被拒绝”的终极解密:当 PHP PDO 遇上 Docker 和一个被遗忘的端口
时长: 00:00 | DP | 2025-12-03 09:03:20群晖 NAS 部署 MySQL Docker 踩坑记:轻松搞定“Permission Denied”权限错误
时长: 00:00 | DP | 2025-12-03 21:19:10PHP 终极指南:如何正确处理并存储 Textarea 中的 Markdown 换行符
时长: 00:00 | DP | 2025-11-20 08:08:00MySQL主键值反转?两行SQL高效搞定,避免踩坑!
时长: 00:00 | DP | 2025-12-03 08:08:00MySQL 数据迁移终极指南:从 A 表到 B 表的 5 种高效方法
时长: 00:00 | DP | 2025-11-21 15:54:24MySQL INSERT SELECT 常见错误解析:语法陷阱与数据截断(错误 1265)
时长: 00:00 | DP | 2025-12-18 04:42:30轻松搞定MySQL外键约束错误:无法TRUNCATE表的终极解决方案
时长: 00:00 | DP | 2026-01-16 08:18:03MySQL字符串拼接权威指南:告别'+',拥抱CONCAT()和CONCAT_WS()
时长: 00:00 | DP | 2025-11-22 00:25:58PHP PDO WHERE 从入门到精通:打造一个强大的动态查询构造器
时长: 00:00 | DP | 2025-12-21 06:17:30HTML `data-*` 妙用:如何优雅地为表格列定义数据类型
时长: 00:00 | DP | 2025-12-26 08:55:50超越简单计数器:如何为你的网站设计专业的PV/UV统计系统
时长: 00:00 | DP | 2025-12-26 21:11:40相关推荐
百万级PV日志表优化实战:从VARCHAR到TINYINT的华丽转身
00:00 | 31次本文记录了一次针对日增百万级PV日志表的数据库优化过程。通过将存储操作系统和浏览器信息的VARCHA...
Mac下NFS共享文件为何凭空多出一份?揭秘“._”幽灵文件与PHP解决方案
00:00 | 45次在macOS上开发并操作NFS或SMB共享目录时,你是否曾困惑为何文件总是成对出现,多出一个以“._...
Shell 妙用:如何将多个命令的输出优雅地写入同一个日志文件?
00:00 | 47次在 Shell 脚本或日常系统管理中,我们经常需要执行一系列命令,并将它们的所有输出(包括标准输出和...
Bootstrap 居中完全指南:从文本水平居中到 Flexbox 垂直居中
00:00 | 45次还在为 Bootstrap 中的元素居中问题烦恼吗?本文为你详细解析如何使用 `.text-cent...