openGauss之TidScan

一. 前言

​ 在openGauss中,TidScan是指过滤谓词中包含ctid信息时,不再全表扫描然后通过eqal比对的方式进行计划,而是通过那到ctid谓词,直接通过tid获取到元组,然后再应用其他的过滤条件来过滤通过ticd获取到的元组。如下所示:

本文主要讲述代码中是如何实现tidscan的。

二. 执行计划生成

执行计划生成的入口在set_plain_rel_pathlist,如下为主要的代码实现流程:

复制代码
set_plain_rel_pathlist
    if (rel->orientation == REL_ROW_ORIENTED)
        create_tidscan_paths(root, rel);
            tidquals = TidQualFromBaseRestrictinfo(rel);
                foreach (l, rel->baserestrictinfo) {
                    rlst = TidQualFromExpr((Node*)rinfo->clause, rel->relid);
                        if (is_opclause(expr)) {      // 等于类型的谓词条件
                            if (IsTidEqualClause((OpExpr*)expr, varno))   // 判断是不是谓词意见是ctid=xxx
                                if (node->opno != TIDEqualOperator)  // 仅仅谓词条件包含tid时才支持生成tidscan
                                     return false;
                         } else {
                         .... // 处理其他类型的谓词条件,比如in等场景
                         }
                }
            if (tidquals != NIL)
                add_path(root, rel, (Path*)create_tidscan_path(root, rel, tidquals));
                    TidPath* pathnode = makeNode(TidPath);
                    pathnode->path.pathtype = T_TidScan;
                    cost_tidscan(&pathnode->path, root, rel, tidquals);
                        foreach (l, tidquals) {
                            if (IsA(lfirst(l), ScalarArrayOpExpr)) {
                                ntuples += estimate_array_length(arraynode); // 如果是in的场景,那么代价为数组的长度
                             else if (IsA(lfirst(l), CurrentOfExpr)) {
                                ntuples++;   // 非数组的场景,tid访问的代价均为1
                             } else {
                                 ntuples++;
                             }
            }             
    }
三. TidScan算子实现

​ ExecTidScan的实现入口在ExecTidScan函数中,主要根据ctid的谓词条件转换成tid数组,依次取tid数组的位置信息拿到元组返回,主要流程如下所示:

复制代码
ExecTidScan
    ExecScan
        ExecScanFetch
            TidNext   // 使用tid直接扫描元组
                TidListCreateByRecursion(node, RELATION_CREATE_BUCKET(heap_relation)); // tid谓词条件转换成tid数组
                    if (expr && IsA(expr, ScalarArrayOpExpr)) {
                        for (i = 0; i < ndatums; i++) {
                            tid_list[num_tids++] = *itemptr;  // 谓词条件转成的tid数组
                        }
                    }
                    tidstate->tss_TidList = tid_list; // 将需要扫描的数组保存在state中
                    tidstate->tss_NumTids = num_tids;
                    tidstate->tss_TidPtr = -1;   // tss_TidPtr指的是当前取tss_TidList哪个下标值去读元组数据
                TidFetchTuple
                    InitTidPtr(node, b_backward);
                        node->tss_TidPtr++;   // 下边++,因此每次TidNext能拿到下一个tid对应的元组
                    ItemPointerData tid = tid_list[node->tss_TidPtr];  // 拿到元组的地址
                    tableam_tops_tuple_fetch_row_version  // 根据tid拿到元组的数据
        if (qual == NULL || ExecQual(qual, econtext)) {   //应用其他的谓词条件,如第一章节中的job = 'ccc'等其他谓词条件
            ....
        }
相关推荐
2501_933670793 小时前
2026秋招数据分析岗备考路线:SQL、BI、项目与面试题拆解
数据库
我要见SA姐15 小时前
告别 Copilot?Codex 本地化部署指南
运维·数据库·机器学习·oracle·回归
xcLeigh6 小时前
聊聊国产化替换:好用数据迁移工具KDMS怎么帮咱们搞定评估难
数据库·sql·数据迁移·kes·kdms
Elastic 中国社区官方博客6 小时前
列式存储并不等同于列式数据库。Columnar 模式为 Elasticsearch 带来了什么
大数据·运维·数据库·elasticsearch·搜索引擎
我要见SA姐17 小时前
用 Claude Code 重构遗留系统:从评估到落地的完整实践指南
数据库·ide·vscode·oracle·编辑器
Nturmoils8 小时前
一份 KDMS 评估报告,怎样排出迁移先后顺序
数据库
这个DBA有点耶8 小时前
异构数据集成怎么做?5 种同步方案对比 + 金融级 CDC 实战解析
数据库·oracle·架构
独泪了无痕8 小时前
SQL函数实战:GREATEST与LEAST的技巧
数据库·sql·mysql
码少女9 小时前
Linux--多路转接之select
java·服务器·数据库
梁辰兴9 小时前
软件工程:软件维护的副作用
数据库·软件工程·梁辰兴·控制方法·软件维护的副作用·副作用类型·副作用原因