暂无图片
暂无图片
13
暂无图片
暂无图片
暂无图片

OceanBase查询处理

OceanBase 2022-10-11
671

OceanBase 数据库目前使用拉取模式的 table_scan 迭代流程,每一行要迭代吐出到 SQL 层实际上是经过了以下几个阶段的:

  1. 每个 SSTable 通过 query range 定位需要扫描的宏块以及相应的微块,对每个微块需要打开扫描,将需要行整体吐出。

  2. memtable/minor sstable/major sstable 多个 iterator 需要分别迭代行。

  3. 通过败者树根据多个 iterator 当前行的 rowkey 是否相同来决定需要拿多少行来参与 fuse。

  4. fuse 后的最终结果行根据需求投影最终结果,拿到最终结果行。

  5. 用最终结果行调用 SQL 的 filter 回调函数进行检查,满足条件继续向上返回。

查询下压

对于 LSM-Tree 架构的存储引擎,在查询的流程一般都会遇到以下几个问题:

  • 过多且频繁的迭代以及主键比较,在较多场景尤其是 OLAP 业务中,大部份表很少更新,数据基本都在基线 major SSTable 中,MEMTable 和 minor SSTable 中只存在很少的增量或者更新数据。理想情况是大部分路径应该都能快速的直接从 major SSTable 扫描,只有当主键存在可能交集时,才尝试几方做 fuse,而目前实现中时需要逐行的和转储以及 MEMTable 中的 iterator 判断主键是否相等。这样一方面是效率显著较低,另一方面也基本丧失了为了向量化的扩展可能。

  • 过滤算子计算的时间过晚,结合上一点,为了保证最终结果的正确,所有行都必须经过 fuse 之后才能保证数据是最新状态,因此目前的过滤算子的检查都是放在每行迭代的最后进行的。

  • 大量无用的投影,从微块扫描吐上来的行需要保证包含最终用户所有需要的列已经投影,经过多次迭代以及 fuse 之后,经过 filter 计算符合条件后可以直接返回,但是如果不符合过滤条件,那么除了 filter 所需列以外的其它投影列都是浪费的。

综上,OceanBase 数据库通过实现过滤算子下压到存储层来解决以上问题,如下图所示:

查询处理

  1. 算子下压,OceanBase 数据库能够快速区分数据没有交集的状态,即能够感知 major SSTable 和增量数据无交集的数据区间,由于该区间的数据只需要访问 major SSTable 即能拿到最新最终状态,因此可以对这段数据直接将过滤算子下压。

  2. 算子过滤,每个下压的 filter 表达式进行解析拆分成存储层能够理解的表达式树,里面包含了对应列信息以及相应的过滤条件表达式。另外,针对过滤条件的复杂度,还能进一步细分为黑盒和白盒两种模式。

    1. 基于 SQL 层的过滤(黑盒),例如 a * 2 > 3 这种带表达式计算类型的过滤条件,存储层是无法处理的,还是需要回调 SQL 层函数处理。此时算子下压到微块 decoder 层后就无法再进一步下压,需要根据 filter node 信息投影出对应列然后调用 SQL 层回调函数来计算结果。

    2. 基于存储的过滤(白盒),例如 a> 1 或者 b = 'abc' 这种简单常见的过滤条件,存储层能够理解语义并处理的 filter node,SQL 层会帮忙进一步解析对应的操作符以及相应的常量表达式,存储层就可以把这个对应的 filter node 继续下压到每一列对应的解码规则中,可以进一步省去投影开销,同时能够充分利用 encoding 信息加速。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论