很多团队在数据量或并发一上来之后,第一反应就是“分库分表”,结果却越分越乱:SQL 无法写、查询效率更低、运维复杂度爆炸,最后甚至有人感叹“还不如不分”。
但真的是“分库分表错了”吗?很可能只是你的路由方案设计不对。
一、常见的“路由坑”
1. 分片键选错了
最常见的问题就是分片键选错了,比如选了用户ID,但业务大部分操作是按订单ID查,导致每次都得查所有分片。
正确的做法是:选最常用作查询条件的字段作为分片键,甚至有时候需要冗余多个键来支持不同维度的查询。
2. 哈希分片导致无法范围查询
如果用一致性哈希做路由,优点是数据分布均匀,但缺点也致命——你无法做范围查询、排序、分页等操作,因为数据被随机分散了。
适用哈希分片的前提是你只需要通过主键精准查询。
3. 路由逻辑写死在代码里
有的系统直接在代码中写:
db_index = user_id % 8
听起来简单,但后续要扩容、合库、变更分片规则,代价极高。建议使用中间件做路由隔离,如 ShardingSphere、MyCAT、Cetus 等。
4. 跨分片 JOIN 查询失败
JOIN 是分库分表后的最大痛点之一。跨库 JOIN 几乎无法原生支持,需要通过:
拆解 SQL 在应用层做 join
缓存关联数据避免 join
引入多维度冗余字段
否则,一旦业务依赖复杂查询,就会遇到各种“不支持”、“查不到”的场景。
二、设计一个好路由方案,需要关注这几点
1. 明确你的主要查询路径
是按用户查订单?按手机号查用户?按时间查交易记录?
路由方案必须围绕“读多的字段”来设计,写入成本反而是次要的。
2. 支持动态扩容
初始可能是 4 个库,后面很可能要变成 8 个、16 个。如果路由不能动态扩展,那等于把自己锁死。
比如:
user_id % n库数
就比写死在 user_id % 4
要好,后续可以读取配置或从注册中心获取。
3. 异常处理要健壮
路由失败怎么处理?目标库挂了怎么办?不能让一个分片的故障拖垮整个业务。
要配合:
路由失败回退机制
慢分片隔离限流
多活读库负载均衡
三、总结
分库分表不是错,用不好才是错。一个合理的路由方案要做到:
路由清晰、可扩展
分片键选对
查询习惯匹配设计
运维成本可控




