SQL 单库单表能撑多大规模?

7次阅读

mysql单表无硬性大小限制,实际瓶颈在于查询性能与写入压力;InnoDB单表可达PB级,但需关注缓冲池、索引设计、大字段处理及分表时机。

SQL 单库单表能撑多大规模?

MySQL 单表到底能到多大?别信“2000万”这个数字

它不是硬限制,而是性能拐点的粗略提示。实际能撑多少,取决于你用什么引擎、字段怎么设计、索引是否合理、硬件是否够劲,以及——你查得有多狠。innodb_file_per_table=ON 时,单表对应一个 .ibd 文件,大小上限主要卡在文件系统(如 ext4/XFS 支持 PB 级单文件),而非 MySQL 自身。但真正拖垮你的,从来不是“存不下”,而是“查不动”或“写太慢”。

为什么 B+ 树深度没你想的那么可怕?

有人总说“500 万行就变深、2000 万行就崩”,这是拿老机械盘 + 小内存 + 默认页大小算的老黄历。现在 SSD 随便上万 IOPS,16KB 页面下,三层 B+ 树就能稳住约 2400 万行(按主键索引、每页 1280 个指针、叶子页存 15 行估算)。真到四层?对查询延迟的影响,在有足够 buffer pool 和 SSD 的情况下,远不如一个 select * FROM huge_table WHERE text_col LIKE '%xxx%' 来得致命。

哪些配置和操作会真实触发瓶颈?

这些才是你上线前该盯死的地方:

  • max_allowed_packet 太小 → 导入大 jsON 或批量插入失败,报错 Packets larger than max_allowed_packet are not allowed
  • innodb_buffer_pool_size 不足 → 缓存命中率暴跌,磁盘随机读暴涨,QPS 断崖下跌
  • 没建好覆盖索引 → WHERE + ORDER BY + LIMIT 组合扫全表,执行计划里出现 using filesortUsing temporary
  • 大字段(TEXT/BLOB)没垂直拆分 → 行溢出导致主表页面碎片化严重,SELECT count(*) 都变慢
  • 没开 innodb_file_per_table(旧库常见)→ 所有表挤在 ibdata1 里,删表不释放空间,运维彻底失控

什么时候该分表,而不是硬扛?

看业务信号,不是看行数:

  • 单表 .ibd 文件 > 50GB,且日常 ALTER TABLE 已超 1 小时 → 分表减小 DDL 风险
  • 高频查询响应时间 > 500ms 且无法通过加索引/改 SQL 优化 → 拆(时间范围分表如 logs_202512,或哈希分表如 user_001
  • 归档需求明确(比如只查近 90 天)→ 直接上 PARTITION BY RANGE (created_at),比手动分表更轻量
  • 备份窗口持续超限,mysqldump 或物理备份耗时翻倍 → 分表后可并行备份,缩短 RPO

真正容易被忽略的,是“写放大”:大表上的 UPDATE 可能触发大量 undo log 和 redo log 写入,尤其在高并发更新同一热点行时,锁争用和刷脏页压力会远早于查询变慢就暴露出来。

text=ZqhQzanResources