分库分表是大表优化的终点而非起点,仅当单表超千万行、查询显著变慢、IO/CPU持续高位且索引与读写分离已失效时才需考虑;应优先垂直分库解耦,再对膨胀表水平分片,并依托ShardingSphere等中间件落地,严防跨库JOIN、ID冲突、迁移风险与深分页问题。

MySQL 大表数据量过大时,分库分表不是第一步,而是性能优化路径的终点。真正需要它,通常意味着单表已超千万行、查询明显变慢、IO或CPU持续高位、读写分离和索引优化已到极限。设计的关键不在于“怎么拆”,而在于“为什么这么拆”和“能否稳住后续运维”。
先确认是否真该分库分表
很多团队在单表刚过500万就急着拆,结果引入复杂性却没解决实际问题。务必验证以下三点:
- 单表行数是否稳定超过1000万,且月增超50万?低于此量级优先做索引优化(如联合索引覆盖高频查询)、SQL改写(避免SELECT *、深分页用游标)、大字段拆出(TEXT/BLOB移至扩展表);
- 数据库服务器资源是否真正打满?查SHOW PROCESSLIST看长事务和慢查询,用iostat -x 1确认磁盘await是否持续>20ms;
- 有没有试过更轻量方案?比如按时间分区(PARTITION BY RANGE (TO_DAYS(create_time))),或冷热分离(近3个月数据留主库,历史归档至ClickHouse)。
选对拆分方式:先垂直、再水平
别一上来就哈希取模分128张表。合理路径是分两步走:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 垂直分库:按业务域切,比如把用户中心、订单中心、商品中心各自独立成库。好处是解耦清晰、迁移成本低、每个库可单独扩容;
- 水平分表:只对其中真正膨胀的表操作,例如order表按user_id哈希分8张(order_0~order_7),确保高频查询(如“查某用户所有订单”)能路由到单表,避免跨表聚合。
注意:分片键必须高频用于WHERE条件、不可变、分布均匀。用create_time范围分片虽易扩容,但容易产生热点(比如新订单全写入最新表)。
落地要靠中间件,别手写路由逻辑
自己在代码里拼order_${userId % 8}看似简单,但会快速失控——分布式事务怎么处理?跨库JOIN怎么查?全局ID怎么生成?推荐直接用成熟中间件:
- ShardingSphere-JDBC:以JAR包形式嵌入应用,零额外服务,适合Spring Boot项目,支持标准分片+读写分离+柔性事务;
- ShardingSphere-Proxy:独立代理层,对应用完全透明,适合多语言混合架构,但运维多一层;
- 避免自研分片框架,尤其不要在DAO层硬编码分库逻辑,否则后续扩容、回滚、监控全部受阻。
必须提前应对的四大后遗症
分完不是结束,而是运维复杂度陡增的开始:
- 跨库JOIN:禁止在SQL里写JOIN user_db.user ON order.user_id = user.id。改为业务层两次查询组装,或通过ETL将维度数据冗余进订单表(如user_name);
- 全局唯一ID:停用自增主键。上线前集成Snowflake或Leaf,确保ID趋势递增、无冲突、可排序;
- 数据迁移:采用双写+校验灰度方案。先同步老库写入新分片,再比对关键字段一致性,最后切读流量;
- 深分页:放弃LIMIT 1000000, 20。改用游标式分页:WHERE create_time 。

















