1. 单表数据量到多大需要考虑分表?"2000 万行"经验值的由来(B+ 树层高与页大小推导)及其局限?
单表数据量到多大需要考虑分表?"2000 万行"这个经验值是怎么来的?它有什么局限?
- B+ 树层高与页大小的推导
- "2000 万行"经验值的来源
- 经验值的局限性与适用场景
是否需要分表,本质取决于索引 B+ 树的高度、热数据能否常驻内存以及查询的磁盘 I/O 次数。以 MySQL InnoDB 为例,默认页大小 16KB,主键为 BIGINT(8 字节)时,非叶子节点每个键约占用 8+6=14 字节,一个 16KB 页可容纳约 161024/14≈1170 个键;若每条记录约 1KB,叶子页可容纳约 16 条记录。于是 2 层 B+ 树可容纳约 117016≈1.9 万行,3 层可容纳约 1170117016≈2190 万行,即约 2000 万行。3 层 B+ 树查一条记录只需 3 次磁盘 I/O,性能良好;一旦超过约 2000 万行,B+ 树可能升为 4 层,每次查询多一次磁盘 I/O,同时索引更大、更难以全部缓存在 Buffer Pool,热数据命中率下降,性能明显劣化。这就是"2000 万行"经验值的由来。
该经验值建立在一系列假设(16KB 页、行约 1KB、主键 8 字节)之上,是 B+ 树/主键索引的粗略推导,不能机械套用。若行很小(如日志型 200 字节),3 层可容纳上亿行;若有大量二级索引、内存不足或写入频繁,即使不足 2000 万行也可能需要分表。判断是否分表应综合"索引层高、Buffer Pool 命中率、查询延迟、写入吞吐、可用内存"以及"是否需要冷热分离/归档",而非单纯看行数。
-- 查看当前表数据量与大小帮助评估
SELECT table_name, table_rows, data_length/1024/1024 AS data_mb
FROM information_schema.tables WHERE table_schema='mydb';