分库分表3-非分片键查询问题与规避方案

一、非分片键查询说明

如果查询时,查询条件带有分片键字段,那么查询时直接定位到一张表/一个库,查询性能比较高

但不可避免的,会有如下场景:查询条件中没有分片键,而是其他字段,此时叫做非分片键查询

例如上述电商场景的订单数据,如果我要根据订单号查询呢?这也是一个比较高频的业务场景

方案选择

  1. 方案一:扫描所有表/库,查询出数据,再聚合,性能低
  2. 方案二:基因法,性能高

二、基因法

基因法是一种在 ID 设计阶段 就考虑到分片的思路。
它利用数学上的一个规律:

当 B 是 2 的 n 次幂时,A % B 等价于 A 的二进制表示的后 n 位。

例如:

9  % 4 = 1    → 1001 的后两位是 01  
10 % 4 = 2    → 1010 的后两位是 10  
15 % 8 = 7    → 1111 的后三位是 111

因此,如果系统中表的数量为 2ⁿ 张,我们只要在生成 ID 时,
将“分片键取模结果”(也就是那后 n 位)嵌入到 ID 的末尾,
就能保证根据该 ID 再次取模时,能路由到与分片键一致的表。

这就是所谓的“在 ID 中注入分片基因”。

三. 我们项目中的场景与问题分析

在本项目中,我们的核心表是 message 表,
它是一个高频写入和查询的表,用于存储会议消息。

我们在设计时选择:

  • 分片键(sharding key)meetingId

  • 分片算法hash(meetingId) % 32 + 1

  • 主键(messageId):使用雪花算法(Snowflake)生成的全局唯一 ID

这意味着,系统在插入消息时,只要知道 meetingId
就能通过哈希算法确定要写入哪张消息表。


四. 为什么我们的项目不存在非分片键查询问题(如何规避)

理论上讲,如果用户只携带了 messageId 而没有 meetingId
那就属于“非分片键查询”场景。
但在我们的系统设计中,这种情况被巧妙规避了。

原因如下 👇

 (1)messageIdmeetingId 是强关联的

message 表中同时保存了 messageIdmeetingId 两个字段。
即使只拿到 messageId,我们也可以通过一次索引表查询反推出 meetingId

SELECT meeting_id 
FROM message_global_index 
WHERE message_id = ?;

随后再利用 hash(meetingId) % 32 即可定位到对应的分表。

✅ 这属于“可反查”的场景,而不是严格意义上的“非分片键查询”。

(2)系统中所有与消息相关的查询均带有 meetingId

在业务逻辑上,任何一条消息都必须属于某个会议。
例如以下几种查询方式:

-- 查询会议下的所有消息
SELECT * FROM message_05 WHERE meeting_id = ?;

-- 查询会议下某一条特定消息
SELECT * FROM message_05 WHERE meeting_id = ? AND message_id = ?;

在这种严格的业务约束下,
系统天然避免了“只靠 messageId 查询”的情况。

 (3)因此messageId 使用雪花算法,不承担分片职责

雪花算法生成的 ID 仅仅保证全局唯一性与时间有序性
并不参与分片逻辑,也不会与 meetingId 冲突。
分片的全部逻辑由 meetingId 控制,雪花 ID 仅仅作为主键使用。

五. 对比总结

场景普通系统我们的项目
分片键缺失会触发全表扫描或需要基因法可通过索引反查 meetingId
主键生成方式基因嵌入或随机 UUID雪花算法(与分片逻辑解耦)
查询设计部分接口无分片键所有查询都基于 meetingId
性能影响存在“非分片键查询”性能瓶颈✅ 已彻底规避此问题

小结

非分片键查询是分库分表系统中最常见、最棘手的问题之一。
然而在本项目中,通过以下两点设计,我们成功规避了该问题:

  1. meetingId 作为核心分片键,所有数据的分布完全由它决定。

  2. messageIdmeetingId 强关联,即使只有 messageId 也能快速反查 meetingId。

因此,项目在分库分表架构下,仍然能保证:

查询高效、路由明确、无全表扫描风险。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值