选好分片键是分库分表提升性能的前提:需确保数据均匀分布、查询高效路由、规避热点、支持平滑扩容。高基数字段(如user_id)优先,避开低区分度字段;分片键须匹配高频查询条件;联合查询需统一分片键;null值须拦截;分区数宜为2的幂次以利扩容。

选好分片键,是分库分表能真正提升性能的前提。光是“能分”不够,关键得让数据散得开、查得快、不扎堆。
数据必须均匀分布
分片后如果某些节点存了70%的数据,其他节点空转,那扩容就失去了意义。判断是否均匀,不能只看字段取值种类多,更要看实际写入时的分布情况:
- 高基数字段优先:用户ID、订单号这类天然离散的整型字段最稳妥;时间戳(如UNIX_TIMESTAMP(create_time))也可用,但需注意写入集中在最近时段可能引发热点
- 避开低区分度字段:性别、状态码、地区编码(如省ID)等枚举类字段,哈希后极易撞进少数几个分区
- 慎用字符串直接哈希:email、手机号虽唯一,但MD5或CRC32后若未做二次取模或重映射,仍可能出现局部聚集
查询模式决定分片价值
分片不是为分而分,是为查而分。一个字段再均匀,如果90%的查询都用不上它,分片就等于白搭:
- 高频等值查询字段最适合作为分片键:比如WHERE user_id = ?几乎出现在所有业务接口中,就能精准路由到单一分片
- 避免把过滤条件少、常被忽略的字段当分片键:例如以source_channel分片,但大部分查询根本不带这个条件,结果每次都要扫全库
- 联合查询场景要拉通考虑:用户表和订单表若经常JOIN,两者必须用相同分片键(如都用user_id),否则关联就得跨库,性能断崖下跌
从源头掐住热点苗头
热点不是等它爆发才处理,而是设计阶段就要预判和规避:
- 警惕自增ID在分布式环境下的连续性:比如雪花ID高位时间戳+中位机器ID,若部署节点少,某段时间生成的ID可能集中在同一段区间,哈希后仍会倾斜
- 注册高峰期新用户ID集中涌入?可对原始ID做一次扰动(如user_id ^ 0x5DEECE66D),打散局部连续性
- NULL值必须拦截:MySQL哈希分区中所有NULL都会落到同一个分区,上线前务必校验并清洗或转为默认非空值
兼顾未来扩展性
今天分8个库,明天想扩到16个,别指望“加个库自动重分”。哈希分片扩容本质是重哈希,必须提前规划:
- 分区数建议设为2的幂次(4/8/16/32),方便后续翻倍扩容时用位运算快速重映射
- 应用层路由逻辑要预留兼容空间:比如用user_id % 16定位分片,比硬编码分库名更易调整
- 避免使用NOW()、RAND()等运行期函数参与分片计算——它们会让分片结果不可预测,也破坏一致性










