openGauss 之索引回表

一. 前言

​ 在openGauss中如果表有索引信息,查询的谓词条件中又包含索引列,openGauss支持通过索引信息快速拿到需要访问元组的位置信息,然后直接到该位置上取出元组数据,称之为回表查询。如下所示,利用索引索引列id=55快速找到t111上对应元组的位置信息,然后通过位置信息拿到id为55的元组中所有列的数据。

本文通过走读openGauss的代码了解openGauss是怎样实现回表查询的。

二. Insert处理

​ 要想实现能快速回表,那么insert时需要保存索引和物理表的位置信息关系。openGauss的insert的入口在ExecInsertT中,保存索引列与元组的位置信息代码流程如下所示:

复制代码
ExecInsertT
    pTSelf = tableam_tops_get_t_self(result_relation_desc, tuple) // pTSelf保存着的是索引对应物理表元组位置信息
        relation->rd_tam_ops->tops_get_t_self(tup);
            HeapamTopsGetTSelf
                return tup->t_self   // 元组的物理表位置信息,即元组的t_self
    ExecInsertIndexTuples
        index_insert(..values, tupleid...)  // value为索引值,tupleid为对应物理表中元组位置信息
            btinsert_internal
                _bt_doinsert
                    _bt_insertonpg
                        _bt_pgaddtup(...itup...)  // 保存索引和其物理表中元组位置信息,itup为索引对应物理表元组位置信息
三. 回表查询

​ 回表查询是在访问索引时,能通过索引的条件拿到元组的tid信息,然后到对应的物理表的tid位置上直接读取元组信息,代码入口在IndexNext,代码流程如下所示:

复制代码
IndexNext
    scan_handler_idx_getnext
        index_getnext
            tid = index_getnext_tid(scan, direction);  // 此函数将会拿到索引对应的物理表的元组地址
                DatumGetBool(FunctionCall2(procedure, PointerGetDatum(scan), Int32GetDatum(direction)));
                    btgettuple
                        _bt_gettuple_internal
                            if (!BTScanPosIsValid(so->currPos))
                                res = _bt_first(scan, dir);   // 首次扫描会将根据谓词条件二分法查找索引,并且保持满足谓词条件的起始地址和条数
                            else
                                res = _bt_next(scan, dir);  // 初始化过之后,只要没有超过条数,直接返回下一条即可
                                    currItem = &so->currPos.items[so->currPos.itemIndex];
                                        scan->xs_ctup.t_self = currItem->heapTid;    // 回表元组的地址信息   
            IndexFetchTuple(scan)   // scan中保存有需要扫描元组的位置信息tid
                tableam_scan_index_fetch_tuple
                    HeapamScanIndexFetchTuple
                        heapam_index_fetch_tuple
                            ItemPointer tid = &scan->xs_ctup.t_self     // 对应上边索引返回的元组的地址信息
                                heap_hot_search_buffer    // 拿到包含所有列完整的元组数据
相关推荐
真上帝的左手5 分钟前
30. 技术专题-‌应用框架组件-缓存-Redis
数据库·redis·分布式·缓存·中间件
雪芽蓝域zzs8 分钟前
第 2 章:整合 MySQL + MyBatis,搭建数据库基础、实体类、Mapper、测试查询
数据库·mysql·mybatis
实泽有之,无泽虚之28 分钟前
SQL Server数据库备份与还原详解
数据库·sqlserver
DevOpenClub34 分钟前
高考一分一段 API:分数查位次、科类枚举与历史对照
linux·数据库·高考
Java后端的Ai之路38 分钟前
Java并发编程07-等待通知机制优化循环等待
java·数据库·python
AllData公司负责人43 分钟前
AllData 可定义数据中台完成信创适配|银河麒麟 + 海光X86 CPU / 华为鲲鹏ARM CPU+ OceanBase / 人大金仓国产化环境部署落地
大数据·arm开发·数据库·人工智能·oceanbase·kingbase
bksczm44 分钟前
C++Redis开发(Ubuntu 22.04)
数据库·redis·缓存
zhangjw341 小时前
1-6 PostgreSQL 特色类型实战:数组、JSON & JSONB、枚举、范围类型
数据库·postgresql
杨云龙UP1 小时前
Oracle 同义词(SYNONYM)详解及 Toad for Oracle SQL 智能补全配置实战
运维·数据库·sql·oracle·同义词·toad·toad for oracle
倔强的石头_1 小时前
MongoDB迁移的新选项:在金仓KES上,用SQL管理文档数据
数据库