MySQL 单表数据量限制
3/1/25About 3 min
MySQL 单表数据量限制
"MySQL 单表不要超过两千万"是流传很广的经验法则。这个数字是怎么来的?它是硬限制还是经验建议?
MySQL 的存储限制
MySQL 本身没有单表行数上限,但有存储层面的天花板:
| 限制项 | 上限 | 说明 |
|---|---|---|
| 单表数据文件大小 | 受文件系统限制 | InnoDB 表空间最大 64TB |
| 单表行数 | 理论无限 | 实际受文件系统和性能制约 |
| 索引数量 | 64 个 | InnoDB 限制 |
所以"两千万"不是 MySQL 的硬限制,而是性能层面的经验值。
为什么是两千万
核心原因在于 InnoDB 的 B+ 树索引结构。
B+ 树高度与查询性能
InnoDB 默认页大小为 16KB。假设:
- 一条记录约 1KB(中等宽度),每页约存 16 条
- B+ 树的非叶子页只存键值 + 页指针,每页约存 1200 个指针
那么不同层级能容纳的数据量:
| B+ 树高度 | 行数估算 |
|---|---|
| 1 层 | ~16 行 |
| 2 层 | ~16 × 1200 ≈ 1.9 万 |
| 3 层 | ~1.9 万 × 1200 ≈ 2280 万 |
| 4 层 | ~2280 万 × 1200 ≈ 273 亿 |
当数据量达到 2000 万级别时,B+ 树高度从 3 层变为 4 层。 多层意味着一次查询要多一次磁盘 IO,这就是性能拐点。
换句话说,"两千万"这个值就是B+ 树 3 层变 4 层的分水岭。
当然实际取决于你的行大小和索引设计,宽表可能几百万就到 4 层了。
实际的性能影响
以主键查询为例:
- 3 层 B+ 树:3 次磁盘 IO 找到数据
- 4 层 B+ 树:4 次磁盘 IO 找到数据
对于机械硬盘(HDD),一次随机 IO 约 10ms,多一层就是多 10ms。但对于 SSD(约 0.1ms),影响小得多。这也是为什么现代 SSD 服务器上,两千万这个数字可以适当放宽。
超过两千万怎么办
1. 优化索引
很多时候慢不是因为数据量大,而是索引没走对。
-- 确保慢查询用到了正确的索引
EXPLAIN SELECT * FROM orders WHERE user_id = 123;2. 水平拆分(分表)
按业务维度拆表:
-- 按年份分表
CREATE TABLE orders_2023 LIKE orders;
CREATE TABLE orders_2024 LIKE orders;3. 分区表
MySQL 原生分区功能,对应用层透明:
ALTER TABLE orders
PARTITION BY RANGE (YEAR(order_date)) (
PARTITION p2022 VALUES LESS THAN (2023),
PARTITION p2023 VALUES LESS THAN (2024),
PARTITION p2024 VALUES LESS THAN (2025)
);4. 分库分表
当单库也扛不住时,用 ShardingSphere、Mycat 等中间件进行分库分表。
5. 冷热分离
将历史数据归档到冷库(如 TiDB、ClickHouse),热库只保留近期活跃数据。
总结
"两千万"是 B+ 树高度从 3 层升到 4 层的经验分水岭,不是绝对不能超过的硬限制。实际情况取决于行大小、索引设计、存储介质(SSD vs HDD)。
超过了也不是世界末日 qWq ——索引优化、垂直/水平拆分、分区表、分库分表等方案足够应对大部分场景。