MySQL分库分表教程:从单表瓶颈到水平拆分

单表数据量涨到千万级后,查询开始变慢、加索引也压不住写入时,就该考虑分库分表了。
但分库分表不是越早越好,它解决的是单库单表的容量和并发瓶颈,代价是跨库事务、跨片查询和运维复杂度上升。
这篇教程按“先判断要不要拆、再选分片键、最后用ShardingSphere落地”的顺序讲,跟着做可以完成一次水平分表验证。

什么情况下才需要拆表

先给一个可参考的判断思路,而不是死数字。
单表行数超过约500万到1000万、单表数据文件超过几GB、写入QPS持续偏高、慢查询集中在同一张大表时,才值得评估拆分。
如果只是偶尔慢,优先做索引优化、读写分离或归档历史数据。

分库分表主要分两种:

  • 垂直拆分:按业务把不同表拆到不同库,比如订单库、用户库分开。
  • 水平拆分:同一张表按规则拆成多张,比如 order_0、order_1,这是本教程重点。

水平拆分的目标是让每条数据有明确归属,查询时能直接定位到某张表,而不是全表扫描。

分片键怎么选

分片键决定数据落到哪张表,选错会导致数据倾斜或跨片查询。

  • 优先选查询条件里最常出现的字段,比如订单表用 user_id 或 order_id。
  • 尽量让分片键分布均匀,避免用性别、状态这类基数低的字段。
  • 如果要按时间范围查,可考虑时间分片,但要注意热点集中在最新分片。

一个常见做法是订单表按 user_id 取模分片,这样同一用户的订单落在同一张表,按用户查询效率高。
代价是按订单号查时需要额外映射,或让订单号里带分片信息。

用ShardingSphere-JDBC做水平分表

下面以 Spring Boot 项目为例,环境为 MySQL 8.x、ShardingSphere-JDBC 5.x,实际版本请以你项目中依赖为准。

第一步,建两张分表,结构完全一致:

CREATE TABLE t_order_0 (
  order_id BIGINT NOT NULL,
  user_id BIGINT NOT NULL,
  amount DECIMAL(10,2),
  PRIMARY KEY (order_id)
);

CREATE TABLE t_order_1 LIKE t_order_0;

第二步,在 pom.xml 引入依赖:


  org.apache.shardingsphere
  shardingsphere-jdbc-core-spring-boot-starter
  5.4.1

第三步,在 application.yml 配置分片规则:

spring:
  shardingsphere:
    datasource:
      names: ds0
      ds0:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://127.0.0.1:3306/demo
        username: root
        password: your_password
    rules:
      sharding:
        tables:
          t_order:
            actual-data-nodes: ds0.t_order_$->{0..1}
            table-strategy:
              standard:
                sharding-column: user_id
                sharding-algorithm-name: order-inline
        sharding-algorithms:
          order-inline:
            type: INLINE
            props:
              algorithm-expression: t_order_$->{user_id % 2}
    props:
      sql-show: true

配置说明:actual-data-nodes 声明真实表,algorithm-expression 用 user_id % 2 决定落表。sql-show:
true
会打印路由后的 SQL,
方便验证。

第四步,启动应用后插入一条 user_id=3 的数据,观察日志中实际执行的 SQL 是否指向 t_order_1。
再去数据库分别查两张表,确认数据只落在其中一张,说明分片生效。

常见报错与避坑

  • 报错“actual-data-nodes not found”:检查库名、表名和表达式是否与实际表一致。
  • 查询走全路由:SQL 中没有带分片键,ShardingSphere 无法定位单表,会并发查所有分片。
  • 跨片分页性能差:LIMIT 分页在分片场景下会归并结果,深分页要改用游标或业务侧限制。
  • 分布式主键冲突:分片后不能依赖单库自增,改用雪花算法或号段模式生成主键。
  • 跨库事务:尽量让同一事务的数据落在同一分片,否则需要引入 Seata 等方案,复杂度明显上升。

重要提醒:分库分表前先备份数据,在测试环境验证路由规则,再考虑上生产。

效果验证与后续扩容

验证分片是否成功,可以看三点:日志里的路由 SQL、两张分表的数据分布、按分片键查询的响应时间。
如果数据明显倾斜,说明分片键或算法需要调整。

后续扩容时,简单的取模算法在增加分片数后会导致大量数据迁移。
生产环境更常用一致性哈希或预分片方案,把扩容成本提前设计进去。

分库分表是架构层面的改动,建议先在小表上跑通流程,再逐步迁移核心表。
如果你还在单表阶段,先把索引和慢查询优化做好,往往能推迟拆分时间。

分享到:
上一篇
MySQL高可用方案怎么选:主从复制到MHA部署实操
下一篇
MySQL InnoDB 优化教程:从缓冲池到日志,零基础也能调对参数
1
系统公告

泽御云中秋国庆双节活动上线:新购8折,拼团3.99元起

尊敬的用户:
泽御云“月满中秋·礼贺国庆”双节活动现已开启,活动时间为2026年9月23日至10月10日。 活动期间可享以下福利:
1. 常规云服务器新购使用优惠码“泽御中秋国庆同乐”,符合条件的订单享8折优惠。
2. 香港精品云服务器5人拼团低至3.99元,部分4核4G套餐3人拼团年付388元,续费同价。
3. 新用户购买年付云服务器,符合活动规则可赠送2个月使用时长。
4. 老用户续费季度赠15天,续费年度赠2个月;活动期间升级配置免收配置迁移手续费。
5. 推荐好友成功下单,符合条件的推荐人可获赠7天服务器使用时长。
6. 活动期间享宕机补偿标准翻倍、简单网站迁移协助及技术工单优先处理权益。
温馨提示:优惠码不适用于拼团套餐、活动轻量产品、年付订单及续费订单;拼团套餐为独立特价活动,不与赠时类福利叠加。赠送时长不可折现、退款或跨账户转移,具体规则以活动页面说明为准。
服务中心
客服
在线客服
24小时为您服务
咨询
联系我们
联系我们,为您的业务提供专属服务。
24/7 技术支持
如果您遇到寻求进一步的帮助,请过工单与我们进行联系。
24/7 即时支持
泽御云
售前客服
泽御云
泽御云
售后客服
泽御云
技术支持
评价
您对当前页面的整体感受是否满意?
😞
非常不满意
😕
不满意
😐
一般
🙂
满意
😊
非常满意