openGauss之NestedLoop Join内表 Reuse

一. 前言

       openGuass支持在做nestloop的时候,支持通过Materialize的方式将内表缓存到内存中,然后外表的数据内表数据进行碰撞的时候,如果内表已经缓存了数据,那么直接从缓存中直接读取内表的数据,从而实现内部数据Reuse。如下所示,不Reuse内表时内部的数据需要读三遍才能完成Join操作,但是内部数据Reuse时,只需要读取一遍即可。

​        在处理内表的“abc”时,外表的”abc“,”ecf“,”klm"的数据要到物理表中读取,但是处理内表的“ecf”和“klm”的数据时,外表不需要再到物理表中读取数据,只需要从物化到内存中读取缓存的数据即可。

​       本文主要走读代码了解openGauss中如何实现外表的物化Reuse能力。

二. 执行计划生成

​      openGuass在NestLoop Join,Append等场景下都会生成物化算子,如下为nestloop场景下生成物化算子的代码执行流程:

add_paths_to_joinrel
    match_unsorted_outer(RelOptInfo* outerrel, RelOptInfo* innerrel)
        foreach (lc1, outerrel->cheapest_total_path) {
            foreach (lc2, innerrel->cheapest_total_path) {
                if (u_sess->attr.attr_sql.enable_material) {
                    matpath = (Path*)create_material_path(inner_cheapest_total);   // 尝试将内表物化
                        cost_material
                            run_cost += 2 * u_sess->attr.attr_sql.cpu_operator_cost * tuples // 物化算子的代价
                }
            }
        }

三.  物化算子的实现

​      物化的算子实现入口在ExecMaterial函数中,其中分成两种实现,一种是并行需要的ExecMaterialAll实现,另外一种就是普通的ExecMaterialOne实现。ExecMaterialOne实现基本上和https://blog.csdn.net/wangfeihuo/article/details/141786234?spm=1001.2014.3001.5501 所说的流程一样。ExecMaterialAll会先把内表的数据全部完成缓存后再返回,主要流程如下所示:

ExecMaterialAll
    for (;;) {     // for 循环会循环取内表的数据,直到取完后退出
        PlanState* outerNode = outerPlanState(node);
        TupleTableSlot* outerslot = ExecProcNode(outerNode);   // 直接从物理表读取数据

        /* subPlan may return NULL */
        if (TupIsNull(outerslot)) {      // 内表的数据已经取完
            break;
        }
        tuplestore_puttupleslot(tuple_store_state, outerslot);   // 缓存
    }
    tuplestore_gettupleslot(tuple_store_state, forward, false, slot)  // 从缓存中读取数据
    return slot;   // 返回元组数据

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值