【数据库内核分析系列】:数据库索引的创建过程

news2025/4/8 0:07:06

文章目录

  • 普通表索引
    • DefineInde
    • Index_create函数
    • index_build
  • 分区表索引

数据库索引可以提高数据的访问速度,openGauss支持唯一索引、多字段索引、部分索引和表达式索引。

  • 行存表(ASTORE存储引擎)支持的索引类型:btree(行存表缺省值)、hash、gin、gist。行存表(USTORE存储引擎)支持的索引类型:ubtree。
  • 列存表支持的索引类型:Psort(列存表缺省值)、btree、gin。
  • 全局临时表不支持GIN索引和Gist索引。

如上一篇分析数据库表的创建过程,standard_ProcessUtility函数会根据nodeTag(parsetree)的值来确定sql的操作类型,create table一般都是进入T_CreateStmt分支调用CreateCommand函数。create index则进入T_IndexStmt分支调用DefineIndex函数。在调用DefineIndex前会首先执行函数transformIndexStmt,如果语句没有指定索引类型则会使用缺省值。

  if (stmt->accessMethod == NULL) {
        if (!isColStore) {
            /* row store using btree index by default */
            if (!RelationIsUstoreFormat(rel)) {
                stmt->accessMethod = DEFAULT_INDEX_TYPE; //  行存表ASTORE存储引擎缺省值btree
            } else {
                stmt->accessMethod = DEFAULT_USTORE_INDEX_TYPE; // 行存表USTORE存储引擎缺省值ubtree
            }
……
            } else {
                /* column store using psort index by default */
                stmt->accessMethod = DEFAULT_CSTORE_INDEX_TYPE; // 列存表缺省值psort
            }
        }

#define DEFAULT_INDEX_TYPE  "btree"
#define DEFAULT_HASH_INDEX_TYPE "hash"
#define DEFAULT_CSTORE_INDEX_TYPE "psort"
#define DEFAULT_GIST_INDEX_TYPE  "gist"
#define CSTORE_BTREE_INDEX_TYPE "cbtree"
#define DEFAULT_GIN_INDEX_TYPE "gin"
#define CSTORE_GINBTREE_INDEX_TYPE "cgin"
#define DEFAULT_USTORE_INDEX_TYPE "ubtree"

普通表索引

DefineInde

DefineIndex为创建索引主入口函数。通常创建索引以Share锁锁定表,允许并发查询,但禁上对表进行修改。如果创建索引时指定关键字CONCURRENTLY以不阻塞DML的方式创建索引,即允许读取和更新表,以ShareUpdateExclusiveLock锁锁定表。

在这里插入图片描述

    lockmode = concurrent ? ShareUpdateExclusiveLock : ShareLock;
    rel = heap_open(relationId, lockmode);

如果没有指定索引名,ChooseIndexName根据规则生成索引名:

    /*
     * Select name for index if caller didn't specify.
     */
    indexRelationName = stmt->idxname;
    if (indexRelationName == NULL) {
        indexRelationName = ChooseIndexName(RelationGetRelationName(rel),
            namespaceId,
            indexColNames,
            stmt->excludeOpNames,
            stmt->primary,
            stmt->isconstraint);

为index_create函数构造参数IndexInfo结构体:

/*
 * Prepare arguments for index_create, primarily an IndexInfo structure.
 * Note that ii_Predicate must be in implicit-AND format.
 */
indexInfo = makeNode(IndexInfo);

Index_create函数创建索引:
/*
* Make the catalog entries for the index, including constraints. Then, if
* not skip_build || concurrent, actually build the index.
*/
indexRelationId = index_create(rel,
……
关闭表并返回索引表id:

    heap_close(rel, NoLock);
    return indexRelationId;

Index_create函数

打开系统表pg_class:

pg_class = heap_open(RelationRelationId, RowExclusiveLock);

heap_create创建relcache和索引物理文件:

    /*
     * create the index relation's relcache entry and physical disk file. (If
     * we fail further down, it's the smgr's responsibility to remove the disk
     * file again.)
     */
    StorageType storage_type = RelationGetStorageType(heapRelation);
    indexRelation = heap_create(indexRelationName, namespaceId, tableSpaceId, indexRelationId, relFileNode,
        RELATION_CREATE_BUCKET(heapRelation) ? heapRelation->rd_bucketoid : InvalidOid, indexTupDesc, relKind,
        relpersistence, isLocalPart, false, shared_relation, mapped_relation, allow_system_table_mods,
        REL_CMPRS_NOT_SUPPORT, (Datum)reloptions, heapRelation->rd_rel->relowner, skip_create_storage,
        isUstore ? TAM_USTORE : TAM_HEAP, /* XXX: Index tables are by default HEAP Table Type */
        relindexsplit, storage_type, extra->crossBucket, accessMethodObjectId);

将索引表元信息存入系统表pg_class:

   /*
     * store index's pg_class entry
     */
    InsertPgClassTuple(
        pg_class, indexRelation, RelationGetRelid(indexRelation), (Datum)0, reloptions, relKind, NULL);
 
    /* done with pg_class */
    heap_close(pg_class, RowExclusiveLock);

将索引表元信息存入系统表pg_index:

     UpdateIndexRelation(indexRelationId,
        heapRelationId,
        indexInfo,
……

Index_build建立索引:

    } else if (extra && (!extra->isPartitionedIndex || extra->isGlobalPartitionedIndex)) {
        /* support regular index or GLOBAL partition index */
        index_build(heapRelation, NULL, indexRelation, NULL, indexInfo, isprimary, false, PARTITION_TYPE(extra));
    }

index_build

index_build调用index_build_storage,如果创建的是btree索引最终调用btbuild,如果是hash索引最终调用hashbuild,如果是psort则最终调用psortbuild,更多索引访问方法的信息可查看系统表pg_am。

stats = index_build_storage(targetHeapRelation, targetIndexRelation, indexInfo);

      
static IndexBuildResult* index_build_storage(Relation heapRelation, Relation indexRelation, IndexInfo* indexInfo)
{
    RegProcedure procedure = indexRelation->rd_am->ambuild;
    Assert(RegProcedureIsValid(procedure));
 
    IndexBuildResult* stats = (IndexBuildResult*)DatumGetPointer(OidFunctionCall3(
        procedure, PointerGetDatum(heapRelation), PointerGetDatum(indexRelation), PointerGetDatum(indexInfo)));
    Assert(PointerIsValid(stats));
    if (RELPERSISTENCE_UNLOGGED == heapRelation->rd_rel->relpersistence) {
        index_build_init_fork(heapRelation, indexRelation);
    }
    return stats;
}
btree索引的procedure为btbuild。

#0  btbuild (fcinfo=0x7fb4f9c63920) at nbtree.cpp:63
#1  0x00000000011fc07d in OidFunctionCall3Coll (functionId=338, collation=0, arg1=140415366247440, arg2=140415366237480, arg3=140415402419864) at fmgr.cpp:1857
#2  0x0000000000c16b77 in index_build_storage (heapRelation=0x7fb50006b410, indexRelation=0x7fb500068d28, indexInfo=0x7fb5022ea698) at index.cpp:2475
#3  0x0000000000c18097 in index_build (heapRelation=0x7fb50006b410, heapPartition=0x0, indexRelation=0x7fb500068d28, indexPartition=0x0, indexInfo=0x7fb5022ea698, isPrimary=false, isreindex=false,
    partitionType=INDEX_CREATE_NONE_PARTITION, parallel=true) at index.cpp:2834

以上函数调用栈如下:

#0 index_build_storage
#1 index_build
#2 index_create
#3 DefineIndex
#4 standard_ProcessUtility
#5 gsaudit_ProcessUtility_hook
#6 pgaudit_ProcessUtility
#7 hypo_utility_hook
#8 ProcessUtility
#9 PortalRunUtility
#10 PortalRun
#11 exec_simple_query
#12 PostgresMain

分区表索引

创建普通表索引语法如下:

CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [schema_name.]index_name ]
{ ON table_name [ USING method ] | [ USING method ] ON table_name }
({ { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] }[, …] )
[ index_option ]
[ WHERE predicate ];

创建分区表索引语法:

CREATE [ UNIQUE ] INDEX [ [schema_name.]index_name ]
{ ON table_name [ USING method ] | [ USING method ] ON table_name }
( {{ column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [ ASC | DESC ] [ NULLS LAST ] }[, …] )
[ LOCAL [ ( { PARTITION index_partition_name [ TABLESPACE index_partition_tablespace ] } [, …] ) ] | GLOBAL ]
[ index_option ]

两者执行流程基本一致,分区表索引在DefineIndex中是遍历每个分区调用partition_index_create。

openGauss: 一款高性能、高安全、高可靠的企业级开源关系型数据库。

🍒如果您觉得博主的文章还不错或者有帮助的话,请关注一下博主,如果三连点赞评论收藏就更好啦!谢谢各位大佬给予的支持!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/109700.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

绿盟SecXOps安全智能分析技术白皮书 模型更新

模型更新 定义内涵 本节的模型更新是指在模型训练完成并正式上线后,由运维人员采集并提供新的数据对 原有模型进行再训练、更新参数的过程。 技术背景 随着时间的推移,由于周期性事件、突变等状况的发生,当下的数据集和之前用于训练 模型…

通用预约小程序,可广泛应用于医疗、政务、教育、培训、体育、金融、生活服务等行业领域,基于腾讯小程序云开发,无须服务器和域名

项目介绍 采用小程序腾讯云技术构建的高效自有业务预约平台解决方案,无需域名和服务器即可搭建。 机构/商户/企业/个体可以利用本软件快速搭建出自有业务预约平台, 小程序在微信里打开,无需下载安装APP以及复杂的注册,即可轻松通…

真香啊,这招可以轻松抓取某音短视频数据(附 Python 代码)

众所周知,某音短视频是没有提供下载链接的,视频号也没下载链接,但我就想下载下来,还有视频下面的评论我也想拿到,那要肿么办呢?其实播放链接和评论是可以拿到的,我来细细道来 文章目录抓包技术提…

C++——STL之list详解

C——STL之list详解🏐什么是list🏐list的使用🏀splice🏀unique🏀remove🏀sort🏐list的实现🏀迭代器类(体会c的优势)⚽迭代器的构造⚽迭代器的模板参数&#x…

Java项目:springboot+vue电影院会员管理系统

作者主页:源码空间站2022 简介:Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 本项目代码架构设计简单,注释齐全,结构清晰,适合同为java初学者参考。 cinema项目是一套电影院会员管理系统…

第十五章 规则学习

15.1 基本概念 机器学习中的规则通常是指语义明确、能描述数据分布所隐含的客观规律或邻域概念、可写成“若…,则…”形式的逻辑规则。规则学习是从训练数据中学习出一组能用于对未见示例进行判别的规则。 与神经网络、支持向量机这样的黑箱模型相比,规则学习具有…

NewStarCTF公开赛week3密码学前两道题的wp

目录一、keyExchange1.原题2.考察知识点与解题思路Diffie-Hellman密钥交换3.解题脚本二、Prof. Shamirs Secret1.原题2.考察知识点与解题思路Shamir 门限方案3.解题脚本一、keyExchange 1.原题 题目给出的是题目给出的是加密过程和输出: from secret import flag…

【LeetCode每日一题:2011. 执行操作后的变量值~~~模拟】

题目描述 存在一种仅支持 4 种操作和 1 个变量 X 的编程语言: X 和 X 使变量 X 的值 加 1 –X 和 X-- 使变量 X 的值 减 1 最初,X 的值是 0 给你一个字符串数组 operations ,这是由操作组成的一个列表,返回执行所有操作后&…

Merge-On-Write 的处理流程

简单来讲,Merge-On-Write 的处理流程是: 对于每一条 Key,查找它在 Base 数据中的位置(rowsetid segmentid 行号) 如果 Key 存在,则将该行数据标记删除。标记删除的信息记录在 Delete Bitmap 中&#xff…

【C++】多态(万字详解) —— 条件 | 虚函数重写 | 抽象类 | 多态的原理

🌈欢迎来到C专栏~~多态 (꒪ꇴ꒪(꒪ꇴ꒪ )🐣,我是Scort目前状态:大三非科班啃C中🌍博客主页:张小姐的猫~江湖背景快上车🚘,握好方向盘跟我有一起打天下嘞!送给自己的一句鸡汤&#x1…

Logoist - 适用于设计师以及初次使用者,快速制作精美 logo

Logoist - 适用于设计师以及初次使用者的快速制作精美 logo 工具 从简单的标识到设计开发。它只需要一点时间来创建令人印象深刻的图像和矢量图形与Logoist。 我们的一体化应用程序为您提供了您需要的一切,将您的创意付诸实践或寻找新的灵感!它适合专业设计师和插画…

阿里云将加速与伙伴合作 促进Web3.0生态发展

12 月 15 日,在Web3.0 Cloud Day Singapore 2022 活动上,阿里云新加坡、南亚和泰国总经理 Dr Derek Wang 表示,阿里云将加速和伙伴的合作以促进创新。“我们正在与我们的合作伙伴合作以实现创新。我们仍然处于 Web 3.0 的早期阶段。我们仍然需…

【蓝桥杯选拔赛真题53】Scratch破解保险柜 少儿编程scratch图形化编程 蓝桥杯选拔赛真题讲解

目录 scratch破解保险柜 一、题目要求 编程实现 二、案例分析 1、角色分析

大数据处理之ClickHouse概述及架构参考(未完)

一、概述 中移某业务拨测系统基于业务数据拨测指标及日志的分析需要,随着Clickhouse在OLAP领域的快速崛起,以及一些特性考虑,比如: 数据量会很大,最好需要分布式; 支持实时写入,支持快速计算&a…

数据库管理-第四十九期 Exadata的存储节点管理(20221223)

数据库管理 2022-12-23第四十九期 Exadata的存储节点管理1 咋个查看数据是否被缓存到闪存卡了没2 EM13.5的Exadata监控3 存储降级总结第四十九期 Exadata的存储节点管理 本周二,抗原终于阴性了,星期三开始就回到现场开始办公。上周既然说了Exadata关于存…

[C++: 引用】

To shine,not be illuminated. 目录 1 引用概念 2 引用特性 3 常引用 4 使用场景 4.1 引用做参数 4.2 做返回值 5 传值、传引用效率比较 6 引用和指针的区别 7 总结 1 引用概念 引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为…

Java+Swing+mysql会员卡管理系统

JavaSwingmysql会员卡管理系统一、系统介绍二、功能展示1.主页页面2.会员信息查询3.会员信息删除三、系统实现1.members.java四、其它1.其他系统实现一、系统介绍 使用 Java 技术开发一个会员卡管理系统,具体实现功能如下: 1. 程序启动显示主界面&#…

Vue:从组件开始学习

文章目录Vue组件生命周期根据官网文档,我们可以快速使用vue3创建自己的应用代码:npm init vuelatest,然后根据自己的需要来选择对应的配置: 默认使用vite来配置项目的。 在main.ts入口文件中,我们可以看到&#xff0…

非零基础自学Golang 第17章 HTTP编程(上) 17.5 知识拓展

非零基础自学Golang 文章目录非零基础自学Golang第17章 HTTP编程(上)17.5 知识拓展17.5.1 curl工具详解第17章 HTTP编程(上) 17.5 知识拓展 17.5.1 curl工具详解 【1】curl 简介 curl是一个利用URL语法在命令行下工作的文件传输工具,于1997年首次发行。它支持文…

Java+MySQL基于ssm的互助救援车队管理系统

此项目能够更全面的为社会贡献爱心,更及时的帮助求助人,然后在后台完成整个过程最后在通过广播好人好事,在高考爱心送子、养老院奉献爱心等活动更能做到统一化,更有序让注册的私家车主有的放矢,供献爱心。现在社会的信…