[Zombodb那些事]Zombodb执行引擎

Zombodb执行引擎

0.前言

我们在使用Zombodb时,会使用一些SQL查询,例如:

CREATE EXTENSION zombodb;
DROP EXTENSION zombodb;
CREATE INDEX idxtest_analyze_text ON test_analyze_text USING zombodb ((test_analyze_text.*));
DROP TABLE idxtest_analyze_text;
ALTER INDEX idxbook SET (options='id=<public.book_content.idxcontent>book_id');

SELECT * 
  FROM book 
 WHERE book ==> 'author:shakespeare and users.full_name:"John Doe"'

这里罗列的SQL不全,只是给大家简单看一下Zombodb的基本用法,像这些SQL从PostgreSQL(以下简称:PG)传递过来,到底经历了什么流程?上面不同类别的SQL语句到底会怎么去执行?ES的Bulk请求的上游是谁?谁来管理ES请求?==>操作符又是怎么识别的?

带着这些疑问,我们来开始Zombodb执行引擎。

Zombodb执行引擎不像PG那样复杂,能搞若干年,Zombodb的执行引擎简单用一幅图概括其核心工作。

  • PG优化器、执行器重写

    • 后面文章会详细展开

  • ES操作API

    • 没错,这里就是来管理上一篇文章写的ES Bulk请求。

看样子是比简单的,但是深挖下去,这一篇文章搞不定,所以我先来个执行引擎轮廓吧。

1fe99d5bee0dbe9e035862b0d84c983d.png

e2dfdcbdb8d1a51dba74774825656a63.png

1.Hooks

Zombodb执行引擎管理了很多Hooks,Zombodb在全局有一个可变的单例对象,所有的操作都是通过EXECUTE_MANAGER来发起调用。

简单说一下Hooks是什么,PG代码里面会提供给第三方回调接口,这便是Hooks,逻辑为:

if (hook) {
 your_hook();
} else {
 default_behavior();
}

这里写了一段伪代码,如果你定义了hook那么就会走你的逻辑,不然就走PG默认行为,所以Hooks就是一堆这种hook的组合。Zombodb这边实现了:

2fbdb862e2ae580707120244c8ebaf4f.png

  • 优化器Planner

优化器里面做了不少工作,例如:ctid重写,表达式重写等等,这一块后面打算单独讲。

  • PG执行器开始 executor_start

执行器开始在Zombodb这边实现比较简单,就是内部维护了一个query_stack结构,往里面插入即可,query_stack结构在本文后续讲,这里理解为一个Vector即可。

  • PG执行器结束 executor_end

执行器结束在Zombodb这边实现就更简单了,直接从Vector的query_stack中pop出去,就完事了。

可以看到PG执行器的Hook逻辑就是类似于现场还原的一个实现。

  • 工具类语句hook process_utility_hook

这里就是实现我们修改表、修改索引别名、删除操作。这里实现比较简单了,看一下代码就懂了。

当然还有其他我们内部定制的Hook,这些就不赘述。

2.执行引擎

接下来就是Zombodb执行引擎的结构了,内部包括:

  • 每个表的元组描述符

元组描述符在这里表示你查询的时候的某些列信息。例如:这里有一个普通的查询,这里id就是tupledesc,另一个工具类查询语句结果中的QUERY PLAN就是tupledesc,这些内容会在PG里面用TupleDescData存起来。

3000d209007278e0561b2de13293e0ed.png

  • 每个表的bulk请求上下文

bulk请求是什么,可以看上一篇文章,这里存储的是BulkContex数据结构,这个数据结构在Zombodb里面结构如下图所示,具体可以看图中注释,没有提到的便是is_shadow字段,这个表示当前索引是否是影子索引。

所谓影子索引表示的它是否被包了一层,然后用户直接看不到,需要回溯看UDF,才理解。例如下面这个便是影子索引。

---非影子索引
SELECT * 
  FROM book 
 WHERE book ==> 'shakespeare';

---影子索引
SELECT * 
  FROM book 
 WHERE my_shadow_func(book) ==> 'shakespeare';
 
CREATE OR REPLACE FUNCTION my_shadow_func(anyelement)
    RETURNS anyelement
    IMMUTABLE STRICT
    LANGUAGE c AS '$libdir/zombodb.so', 'shadow_wrapper';

f31f9f775d171a7e6e439cb4e1078da0.png

  • 使用过的所有事务id

一个完整的事务可能包括事务发起、事务中、事务提交、事务回滚等其中多个步骤。而Zombodb执行引擎里面使用了一个hashset存储之前已经提交的所有事务id,防止重复提交。对外的API如下:

事务开始:push_xid,将当前事务id放入hashset中,并发起Bulk事务正在进行的请求。

事务提交:commit,等待所有hashset中的事务id被提交,如果有失败,就会panic掉,提交后,释放执行引擎的所有成员占用的内存。

事务回滚:abort,给ES Bulk发起立刻终止请求并释放执行引擎的所有成员占用的内存。

  • 所有查询的query_desc

这个就是前面提到的query_stack,有一个数组维护,里面存储了一个tuple(查询描述符,查询状态)。

  • 事务回调是否注册标记

在PG/GP里面会有回调函数,用户可以进行注册,例如:两阶段提交中/后的处理回调,都可以自定义逻辑,例如:在Zombodb里面实现了PreCommit、Abort,这里便会调用前面的commit与abort。

设置完毕这些回调函数,需要设置注册标记为true,因为这些只需要注册一次就行(执行引擎对象是全局单例)。

f2ba3a76832b7191c61e6011848dd814.png

3.查询状态

Zombodb中提供了两个比较特殊的函数:

  • zdb.scores

  • zdb.highlights

一个可以用来返回ES的score,并放到order by之后用来排序。

另一个是使用ES的文档高亮特性,对查询结果进行高亮显示。

为何这里会有一个查询状态呢?单独还放到了执行引擎里面,像其他的zdb查询缺没有放到执行引擎里面,例如:

zdb.terms

要回答这个问题,首先我们需要知道这两个函数的实现入参都有一个ctid,而根据Zombodb代码中的注释与调用入口,可以发现这两个放到执行引擎里面,是为了方便解决HOT问题。

更复杂的解释,等后面研究一下这里面的门道吧,还有不少东西探究。

本节完~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值