-
Notifications
You must be signed in to change notification settings - Fork 64
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
分库分表:范围查询支持 #168
Comments
如果 将 Predicate 下沉,岂不是新增一个hash实现,就要实现一次?个人倾向于把操作符下沉,到sharding里面 type Request struct { 、、、 |
|
|
对于 IN、NOT IN 是否可以分解成颗粒度更小的操作符计算 |
是的,要拆解成操作符和算法两个部分。然后算法会组装操作符 |
|
我觉得后面要考虑设计改成 #187 中的 aggregator 的设计。但是可能要更加难改,因为这边会涉及到递归的过程。 又或者,我们可以考虑定义一个新接口: type Sharding interface {
OnEq()
OnLt()
} 等。 不过我大概评估了一下,都不是很容易。 后面我们实现范围分库分表的时候,再重构哈希部分,看能否找出一个更加优雅的方案 |
仅限中文
背景
在最开始的时候,我们支持了 EQ 这种写法,AND 和 OR,并且在 #167 里面提及支持 NOT 写法。现在我们要进一步考虑剩余的操作符:
还有一个比较特殊的 !=,我会单独创建一个 issue,因为 != 可以看做是 NOT 的一种特殊场景。在 != 之下,就是广播的候选节点 - (= 确定的节点)。
很明显,我们这一次打算支持的就是范围查询。
使用场景
范围查询对于不同的分库分表规则来说目标表的确定是完全不同的。
哈希分库分表
假如说我们的 order 分库分表规则是 user_id%32 来分表。那么我们会面临这种困境,假如说分库分表的条件:
这种处理方案是有缺陷的,比如说:
user_id > 1000 AND user_id < 10
:那么先单一一个条件考察 user_id > 1000 会命中所有的表;user_id < 10 则只会命中全部集群上的部分库(db_[0,9])和部分表。那么根据 AND 的运算规则进行求交集,最终会选择第二个条件的所有的表。但是我们手动分析就知道,这个查询条件是查询不到任何数据的。那么有些分库分表会引入一些SQL优化,就能一定程度上解决这种问题。
分库和分集群都是类似的。
范围分库分表
假如说我们的 order 分库分表规则是 user_id 每 1000 分一段。比如说 [0, 1000) 是一段,[1000,2000) 是一段...
哈希分库分表
哈希分库分表规则在范围查询里面,几乎都是只能使用广播来进行处理。但是在一些边缘场景里面,存在一点优化的可能,但是实际上并没有必要去执行这种优化。
比如说对于 user_id %3 的分表,当查询条件是 user_id < 100 的时候,很显然是广播;但是如果查询条件是 user_id < 1,那么实际上我们可以确定只会命中 user_tab_0 这张表。
总结起来就是:对于哈希分库分表来说,在最大值和最小值附近,是可以不用广播的。
不过这种优化价值实在不大,所以没有什么必要去做优化。
综合分库分表
假如说我们的分库分表规则是
$region.mycompany.com:3306/order_db_(@user_id%32).order_tab_(@user_id/32%32)
。那么本质上还是按照 AND,OR 来组合整个分集群分库分表。而对于具体的一条规则,则是参考范围分库分表和哈希分库分表来进行处理。设计
在考虑支持范围查询的情况下,需要对已有的接口做一个较大的改造:
也就是我们需要把第二个参数改造成为 Predicate。在这种情况下,意味着我们要把 AND 和 OR 的逻辑也下沉到具体的算法实现里面。
很显然这个 Predicate 就是我们在构造 WHERE 的时候把所有的查询条件 AND 成一个之后的产物。当然,这个地方也可以考虑将 where 定义为 []Predicate。
紧接着,我们在 internal 里面新建一个包,叫做 expression,然后将 eorm 包里面的 Predicate 结构体挪下去。同时在 eorm 里面定义一个同名的结构体 Predicate:
这里面比较麻烦的是在 eorm 本身里面将 Predicate 定义成为了一个 binaryExpression 的衍生类型,所以在重构的时候,需要将所有的 expression 实现都挪下去。同时,在 eorm 里面定义对应的别名。
而后在具体的实现里面完成分库分表的逻辑。
The text was updated successfully, but these errors were encountered: