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.youkuaiyun.com/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;   // 返回元组数据

<think> 首先,用户的问题是:“我想查找在ABAP中直接输出内数据的方法 请问ABAP中直接输出内数据的方法”。我需要基于提供的引用和系统指令来回答这个问题。 系统指令: - 所有行内数学达式必须使用$...$格式(但这个问题不涉及数学,所以可能不需要)。 - 独立公式使用$$...$$格式(同样,不适用)。 - LaTeX语法正确(不直接相关)。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如[^1]。 - 用户可见层:回答结构清晰,帮助用户逐步解决问题,保证回答真实可靠。 引用的内容: - 引用[1]:描述了ABAP内的基本概念,类似于二维数组。 - 引用[2]:ABAP内操作的基本语法,如READ语句和LOOP语句。 - 引用[3]:ABAP内数据操作,如插入数据。 - 引用[4]:ABAP内容输出,展示了如何添加字段到内并显示数据。 用户的问题是关于“直接输出内数据的方法”。引用[4]似乎直接相关,因为它讨论了输出内数据。 从引用[4]: - 它提到使用`ADD_FIELD`来定义字段,然后`DISPLAY_DATA`来显示数据。 - 示例代码:`DISPLAY_DATA ITAB ''.` 这看起来像是输出内数据的命令。 在ABAP中,输出内数据的方法通常包括: 1. **使用WRITE语句**:在LOOP中遍历内并输出每行。 2. **使用ALV网格**:更高级的,用于显示格数据。 3. **使用内输出函数**:如CL_SALV_TABLE来显示ALV列。 引用[4]中的`DISPLAY_DATA`可能是一个自定义函数或示例代码。在标准ABAP中,常用的方法是使用ALV(ABAP List Viewer)来输出内数据。 基于引用[4],我可以构建一个回答: - 步骤1:定义内结构。 - 步骤2:填充内数据。 - 步骤3:使用函数或语句输出数据。 标准方法是: - 使用`WRITE`语句在循环中输出。 - 使用`CL_SALV_TABLE=>DISPLAY`来显示ALV网格。 引用[4]中的代码: - `ADD_FIELD`:添加字段到输出结构。 - `DISPLAY_DATA`:显示数据。这可能是一个自定义方法,但在标准ABAP中,我们使用`CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'`或类似函数。 用户指定了“直接输出”,可能意味着简单的方法。引用[2]中提到LOOP语句,可以用于输出。 结构回答: 1. 介绍内输出方法。 2. 提供示例代码。 3. 基于引用添加标识。 4. 生成相关问题。 回答结构: - 开头解释方法。 - 步骤清晰。 - 代码块展示。 - 引用来源。 - 结束生成相关问题。 生成相关问题: - 类似于示例,例如: 1. ABAP中如何优化内输出性能? 2. ALV网格的使用方法? 3. 其他输出方式比较? 确保使用中文。 </think> ### ABAP中直接输出内数据的方法 在ABAP中,内是用于存储多行数据的动态内存结构(类似于二维数组)。直接输出内数据主要通过两种方式实现:简单循环输出(使用`WRITE`语句)或高级格输出(使用ALV网格)。下面我将逐步解释这些方法,并提供示例代码。所有方法都基于ABAP标准语法,确保真实可靠。 #### 方法1: 使用LOOP和WRITE语句循环输出 这是最直接的方法,通过循环遍历内每一行,并使用`WRITE`语句输出字段值。适用于快速调试或简单数据预览。 1. **定义内结构**:首先声明内类型和结构。 2. **填充数据**:向内插入数据(例如通过`APPEND`或`INSERT`)。 3. **循环输出**:使用`LOOP AT`遍历内,并用`WRITE`输出每个字段。 示例代码: ```abap REPORT ZOUTPUT_ITAB_DEMO. * 步骤1: 定义内结构 TYPES: BEGIN OF ty_structure, id TYPE char5, name TYPE char20, value TYPE i, END OF ty_structure. DATA: lt_itab TYPE TABLE OF ty_structure, " 定义内 ls_line TYPE ty_structure. " 定义工作区 * 步骤2: 填充内数据 ls_line-id = '001'. ls_line-name = 'Item A'. ls_line-value = 100. APPEND ls_line TO lt_itab. ls_line-id = '002'. ls_line-name = 'Item B'. ls_line-value = 200. APPEND ls_line TO lt_itab. * 步骤3: 循环输出内数据 LOOP AT lt_itab INTO ls_line. WRITE: / 'ID:', ls_line-id, " / 示换行 'Name:', ls_line-name, 'Value:', ls_line-value. ENDLOOP. ``` - **输出效果**:程序运行时,会在屏幕上显示: ``` ID: 001 Name: Item A Value: 100 ID: 002 Name: Item B Value: 200 ``` - **优点**:简单易用,无需额外函数。 - **缺点**:格式不美观,不适合大量数据输出;常用于测试环境[^2]。 #### 方法2: 使用ALV网格输出(推荐) ALV(ABAP List Viewer)是标准工具,提供格化输出(支持排序、筛选等功能)。使用`CL_SALV_TABLE`类实现高效输出。 1. **定义内和结构**:同上。 2. **调用ALV函数**:使用`CL_SALV_TABLE=>FACTORY`创建并显示网格。 3. **自定义输出**:可选添加标题或调整列宽。 示例代码: ```abap REPORT ZALV_OUTPUT_DEMO. TYPES: BEGIN OF ty_structure, id TYPE char5, name TYPE char20, value TYPE i, END OF ty_structure. DATA: lt_itab TYPE TABLE OF ty_structure, ls_line TYPE ty_structure. * 填充数据(略,同上示例) * 创建并显示ALV网格 DATA: lo_alv TYPE REF TO cl_salv_table. TRY. " 创建ALV对象 cl_salv_table=>factory( IMPORTING r_salv_table = lo_alv CHANGING t_table = lt_itab ). " 设置标题 lo_alv->get_display_settings( )->set_list_header( '内输出示例' ). " 显示网格 lo_alv->display( ). CATCH cx_salv_msg INTO DATA(lx_error). WRITE: / '错误:', lx_error->get_text( ). ENDTRY. ``` - **输出效果**:生成交互式格,支持点击列头排序、导出Excel等功能。 - **优点**:专业美观,适用于生产环境;引用[4]中类似方法通过`DISPLAY_DATA`实现高级输出(但`CL_SALV_TABLE`是标准替代)[^4]。 - **注意事项**:确保系统支持ALV库(通常SAP GUI已内置)。 #### 方法3: 使用内输出函数(如REUSE_ALV_GRID_DISPLAY) 对于旧系统,可以使用函数模块`REUSE_ALV_GRID_DISPLAY`输出。类似于ALV网格,但语法更繁琐(不推荐新项目使用)。 ```abap CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY' EXPORTING i_structure_name = 'TY_STRUCTURE' " 结构名 TABLES t_outtab = lt_itab. " 内名 ``` ### 选择建议 - **简单输出**:用`LOOP`和`WRITE`(快速调试)。 - **正式输出**:用`CL_SALV_TABLE`(功能丰富)。 - 所有方法都依赖于内结构的正确定义,内在程序运行时动态存储数据,便于操作[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值