1GB 硬盘能存储多少条 MySQL 数据,完全取决于单行数据的实际磁盘占用。与 Buffer Pool 不同,硬盘存储受行格式、索引、空值、碎片等多重因素影响。
一、MySQL InnoDB 磁盘存储结构
1.基本单元:页(Page)
- 大小:16 KB(默认)
- 内容:
- 数据行(聚簇索引 = 行数据)
- 索引记录(二级索引)
- 页头/尾(约 200 字节)
- 预留空间(
innodb_fill_factor控制,通常留 1/16)
✅有效数据容量:
每页 ≈ 15 KB 可用
2.行存储开销
| 组件 | 大小 | 说明 |
|---|---|---|
| 事务ID | 6 字节 | MVCC 必需 |
| 回滚指针 | 7 字节 | MVCC 必需 |
| NULL 位图 | (列数+7)/8字节 | 每列 1 bit |
| 变长字段长度列表 | 1~2 字节/字段 | VARCHAR/TEXT 等 |
| 溢出页指针 | 20 字节/大字段 | TEXT/BLOB 超 768 字节时 |
二、核心估算公式
\text{总行数} \approx \frac{\text{硬盘容量} \times \text{页利用率}}{\text{平均每行磁盘占用}}- 硬盘容量= 1 GB = 1,073,741,824 字节
- 页利用率≈ 15/16 = 93.75%(预留空间)
- 有效容量≈1,006,632,960 字节
⚠️注意:
此公式仅计算数据 + 二级索引,不含 binlog、undo log、系统表空间。
三、典型场景估算
场景 1:极简表(无索引)
CREATETABLEt(idINTPRIMARYKEY,valTINYINT);- 单行大小:
4 (id) + 1 (val) + 6+7 (系统列) + 1 (NULL 位图) ≈19 字节 - 每页行数:15,360 / 19 ≈808 行
- 1GB 可存:
1,006,632,960 / 19 ≈ 52,980,000 行(5298 万行)
场景 2:标准业务表(含索引)
CREATETABLEusers(idINTPRIMARYKEY,emailVARCHAR(100)NOTNULL,nameVARCHAR(50),INDEXidx_email(email));- 聚簇索引行:
4+100+50 + 13 + 2 (变长列表) + 1 ≈170 字节 - 二级索引行(idx_email):
100 (email) + 4 (主键) + 1 (变长) ≈105 字节 - 总行均摊:170 + 105 =275 字节
- 1GB 可存:
1,006,632,960 / 275 ≈ 3,660,000 行(366 万行)
场景 3:宽表(含 TEXT)
CREATETABLEarticles(idBIGINTPRIMARYKEY,titleVARCHAR(200),contentTEXT);- 假设:
title平均 100 字节content平均 10KB(存溢出页)
- 主键页行大小:
8+100 + 13 + 2 + 20 (溢出指针) ≈143 字节 - 溢出页:
每 10KB 内容占 1 个 16KB 页(利用率 62.5%) - 总占用:
主键页 143B + 溢出页 16,384B ≈16,527 字节/行 - 1GB 可存:
1,006,632,960 / 16,527 ≈ 60,900 行(6 万行)
四、关键影响因素
| 因素 | 影响 | 优化方向 |
|---|---|---|
| 行格式 | COMPACT vs DYNAMIC 影响溢出策略 | 用DYNAMIC减少碎片 |
| 索引数量 | 每个索引增加存储 | 删除未使用索引 |
| VARCHAR 长度 | 声明长度影响 NULL 位图 | 按实际需求定义 |
| 数据碎片 | DELETE 后空间不立即释放 | 定期OPTIMIZE TABLE |
| 压缩表 | KEY_BLOCK_SIZE=8K→ 页压缩 | 读多写少场景可用 |
五、精确计算步骤
1.获取表实际大小
SELECTTABLE_ROWS,DATA_LENGTH+INDEX_LENGTHAStotal_bytesFROMinformation_schema.TABLESWHERETABLE_SCHEMA='your_db'ANDTABLE_NAME='your_table';2.计算平均每行磁盘占用
-- 假设结果:TABLE_ROWS=1000000, total_bytes=200000000-- avg_row_size = 200 bytes3.代入公式
1GB 可存行数 = 1,006,632,960 / avg_row_size六、生产注意事项
预留空间:
- 文件系统需保留 5~10% 空闲(防写满崩溃)
- InnoDB 需要 undo log、redo log 空间
监控真实用量:
-- 查看表空间文件大小ls-lh/var/lib/mysql/your_db/your_table.ibd避免低估:
SHOW TABLE STATUS的Avg_row_length不含索引!- 必须用
DATA_LENGTH + INDEX_LENGTH
总结
- 1GB 硬盘可存行数范围:6 万 ~ 5000 万行
- 决定性因素:单行磁盘占用(含索引)
- 工程原则:
“不要相信理论最小值,而要用生产数据反推”。
通过information_schema获取真实avg_row_size,方能精准规划存储。