阅读(2467) (13)

Mycat2 索引字段分析

2021-09-09 15:00:06 更新

Mycat2是分库分表型数据库(中间件),具有逻辑库,逻辑表概念,其中对于分片表类型,使用特定的规则组织'行数据'在多个物理表中存储.而SQL查询分片表的时候,正确使用谓词,Mycat2分析出仅需扫描的物理表,则可在执行阶段大大减少需要使用的连接,IO耗时,因为谓词不符合数据分布,查询的结果集就是空的.(v1.18提供索引字段分析)

在分库分表数据库中,使用不同的数据定位字段减少扫描的范围,它们是分表键,分库键,全局二级索引等.下推它们有着索引字段分析相似的功能.索引字段分析在数据库中至关重要.通常我们判断SQL能否使用哪种扫描数据方式就可以大致判断SQL的查询效率,对于分库分表中间件来说,尽可能减少扫描范围,甚至严格保证扫描的存储节点只有一个存储节点才是正确的用法.

索引字段分析的工作过程

非DNF检查

首次,优化器会提取下压到表扫描算子上的谓词,并把他们做disjunction(DNF)转换,试图得到一组or相邻的表达式,如果该表达式的数量是1,则表示该组表达式没有or运算,则可继续进行谓词分析,否则不满足谓词分析约束.

RexNode:{id = 1 or id = 2} → List<RexNode>[{id = 1},{id = 2}]

W=P1∨P2∨P3∨...Pn

特殊表达式扩展

其次,对谓词表达式扩展.在这里我们可以把一些特殊意义的表达式扩展,比如
id between 1 and 3 → 1 <= id and id <= 3
这样的好处与括号()表达优先级差不多,表示该表达式是一个整体,它们不被CNF/DNF影响.

CNF扩展

然后,对谓词进行CNF分析.得到一组and相邻的表达式.
RexNode:{id = 1 and id = 2} → List<RexNode>[{id = 1},{id = 2}]
W=P1^P2^P3^...Pn

索引应用

因为分片表可能存在多个索引信息,它们依次应用CNF扩展的结果.

提取索引字段

使用谓词检查语法检查and表达式中的每个表达式,提取scan_binary_expr这个层次的语法树,检查其中的字段是否索引字段,把它们转换成谓词节点并依照遍历顺序收集起来,与常规的解析器不同不符合语法的部分不会发生异常,直接跳过.

谓词检查语法

and_expr : scan_binary_expr 'AND' scan_binary_expr


scan_binary_expr : left_expr '=' right_expr 
                                 | left_expr '<' right_expr 
                 | left_expr '>' right_expr 
                 | left_expr '<=' right_expr 
                 | left_expr '>=' right_expr 
                 | right_expr '=' left_expr 
                 | right_expr '<' left_expr 
                 | right_expr '>' left_expr 
                 | right_expr '<=' left_expr 
                 | right_expr '>=' left_expr
                 | ...
right_expr : LITERAL | DYNAMIC_PARAM | CAST LITERAL
left_expr : COLUMN | cast_expr
cast_expr : CAST right_expr |  CAST left_expr 

谓词分解

将谓词分解为等值查询,范围查询,剩余查询三种类型 type = 'famliy' and score < 60 and score >=0

而索引谓词分析的目标则是提取 或者

对于相同的字段,为了减少扫描范围,显然总是比 更优

一些规约

索引最左匹配原则

做左到右尽可能扫描指定的运算符,遇到不是需要的运算符则停止扫描

分解点查询谓词节点

应用索引最左匹配原则(做左到右尽可能扫描=的条件),检查是否点查询并把它们转换成点查询条件组,即可下推索引谓词组,而不能转换的谓词节点构成剩余条件组.

分解范围查询谓词节点

与分解点查询谓词节点相似,范围查询也是应用索引最左匹配原则(做左到右尽可能扫描>=,>等条件),检查是否点查询并把它们转换成上界/下界条件组,即可下推索引谓词组,而不能转换的谓词节点构成剩余条件组.这里的上下界条件组中每个条件不具有between语义.上界与下界是独立的条件.
score < 60 and score >=0 → [{score <60},{score >= 0}]

注解选择索引结果

最后,可能得到一组索引信息分析得到的结果,如果谓词分析器带有了注解要求的索引,在结果中有,则返回它的索引结果.(所以错误的注解可能导致无法使用真正有效的索引)

最终的索引分析结果

对它们的权重进行排序,返回权重最高的索引信息.

索引结果转换至分片条件

每个索引谓词都有它们的类型,比如点查询或者范围查询.对于点查询,可以直接调用分片算法的点查接口就可以得到存储节点的信息.而对于范围查询,我们可以检查上界下界条件,并进一步把它们转换成查询区间,然后调用分片算法的范围查询接口即可.

键的优先级

索引结果可能存在以下情况

一个索引结果有多个不同的字段

多个索引结果,这里仅讨论多个索引结果之间如何挑选最优的.

如果一个谓词中出现多个字段,而这些字段中有多个是可以定位数据分布,但是它们的执行代价,扫描范围可能相同也可能不相同,有些需要额外的IO,连接才可以完成数据定位.这个情况下,我们需要定义这些定位数据分布的索引字段之间的优先级,从中选择最有效的字段来定位数据.一般来说,存在以下规则.

等值查询总是比范围查询更优

分表键总是比分库键更优

...

对于难以判断那种索引更优或者索引性能随着数据量改变的情况,可以使用代价分析判断.