单库单表什么时候撑不住

业务早期,一张订单表、一个用户库就够用。但随着数据量涨到几千万行、并发读写冲到几千 QPS,单库单表会依次撞上三堵墙:单表索引体积过大导致查询变慢、单机连接数与内存到顶、备份和迁移时间越来越长。这时加机器、加缓存只能缓解,真正的解法是把数据拆开,让请求落到更小的表和库上。

分库分表不是银弹,它把一个简单的数据库问题,换成了分布式数据路由、跨片查询、分布式事务、扩容迁移这一整套复杂问题。所以原则很简单:能不分就不分,先做索引、读写分离、缓存;真到了单表上亿行、单机扛不住,再上分库分表。

本文核心知识点
  • 垂直拆分按业务域把不同表拆到不同库,降低单库压力。
  • 水平切分同一张表按某个键拆成多片,数据被分散到各片。
  • 分片键决定一条数据落在哪片,选不好会热点倾斜。
  • 中间件ShardingSphere 把路由逻辑从业务代码里剥离出来。
分库分表配图:蓝色渐变背景上方一个大型数据库圆柱,经发光分流箭头向下连接四个并排的小型数据库圆柱,扁平科技插画
上方逻辑库经路由层分流到下方四个物理分片,数据被水平切开。

垂直拆分与水平切分

两种拆法解决不同问题:

  • 垂直拆分(按业务):把用户、订单、商品分别拆到独立的库,每个库只服务自己的业务域。它解决的是单库表太多、字段太杂、团队耦合的问题,不解决单表太大的问题。
  • 水平切分(按数据行):订单表还是那张订单表,但按 user_id 或 order_id 取模,拆成 order_0、order_1 一直到 order_15,每个分片存一部分数据。它直接解决单表数据量过大的问题。

真实项目里往往两步都做:先垂直把业务拆库,再对订单这种大表做水平切分。垂直拆完之后,跨库的关联查询(比如查用户同时带出订单)要靠应用层组装或冗余字段,不能再用单库 join。

分片键怎么选

分片键是水平切分的命门,选它要同时满足三点:绝大多数查询都带这个键、数据分布均匀、尽量少出现跨片。

  • 用用户类查询为主,就选 user_id——同一个用户的订单落在同一片,列表查询只打一片。
  • 用订单号直接查详情,就选 order_id,但要保证订单号本身编码了分片信息,否则拿订单号查时不知道去哪片。
  • 别用自增主键取模,容易把热点都压在最新那片;也别用时间做唯一分片键,新数据永远打在同一台机器上,形成热点。

常见做法是把分片信息编码进分布式 ID 里:ID 的某几位表示分片号,这样拿到 ID 就知道路由,又避免了取模带来的数据倾斜。

ShardingSphere 的两种接入方式

ShardingSphere 提供两种形态,业务方都感觉不到分片的存在:

  • ShardingSphere-JDBC:一个 JDBC 驱动层的增强包,以 jar 形式嵌进应用,直接在进程内做 SQL 解析和路由。轻量、无额外部署,适合 Java 应用直连。
  • ShardingSphere-Proxy:一个独立部署的代理服务,对外暴露 MySQL 协议,应用连它就像连一个普通 MySQL。多语言、多应用都能共用同一套路由规则。

选哪个看团队:单语言、追求性能用 JDBC;多语言、想集中治理用 Proxy。两者可以混用,Proxy 前面还能再挂一层负载均衡。

分片规则与路由配置

核心是告诉中间件:逻辑表叫什么、有哪些真实数据源、按什么键、用什么算法切。一段概念性配置大致如下:

# 逻辑表 order_item 落在 ds0、ds1 两个库
# 每个库内 order 表按 order_id 取模拆成 16 张
tables:
  order:
    actualDataNodes: ds${0..1}.order_${0..15}
    tableStrategy:
      standard:
        shardingColumn: order_id
        shardingAlgorithmName: mod_16

中间件拿到 SQL 后做三件事:解析 SQL、识别分片键、按算法把逻辑 SQL 改写成对具体真实表的物理 SQL 并并行下发。对带分片键的查询,只打命中的那一片;不带分片键的查询,则广播到所有分片,再由中间件合并结果——这就是为什么跨片查询要尽量避免。

分布式 ID 与跨片查询

分库分表后,数据库自增主键就废了,因为每张表都是独立的、自增会撞号。必须用分布式 ID:雪花算法(Snowflake)这类把时间、机器号、序列号拼进一个 64 位长整数的方案最常用,趋势递增、本地生成、不依赖中心。

跨片查询的坑要提前知道:不带分片键的列表查询要扫所有片再归并,分页、排序、count 都会变慢。应对办法:让高频查询都带分片键;必须全局检索的需求,交给 Elasticsearch 这类搜索引擎去做,而不是硬在分片库上扫。分布式事务这块可参考本站《分布式事务与一致性实战》。