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


## 普通表索引


### DefineInde


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


![在这里插入图片描述](https://img-blog.csdnimg.cn/5a0a45574aa84a7889becbb0f9b486f3.png)



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: 一款高性能、高安全、高可靠的企业级开源关系型数据库。](https://gitee.com/vip204888)


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






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值