2021SC@SDUSC
本篇博客主要讲解GiST索引创建以及删除的相关函数
这里写目录标题
GIST创建
GIST创建相关函数主要在gistbuild.c文件中,我们来分析一下重要的函数和数据结构
相关数据结构
GISTBuildState
typedef struct
{
Relation indexrel;//索引关系
Relation heaprel;//堆关系
GISTSTATE *giststate;
int64 indtuples; /* 索引元组数量 */
int64 indtuplesSize; /* 所有索引元组的总大小*/
Size freespace; /*页面上空闲空间*/
/*
在缓冲构建期间使用的额外数据结构。
*/
GISTBuildBuffers *gfbb;//“gfbb”包含与管理构建缓冲区相关的信息。
HTAB *parentMap;//内部节点的父节点
GistBufferingMode bufferingMode;
} GISTBuildState;
GISTInsertStack
在插入索引元组中,会生成 GISTInsertStack的数据结构,这对于GIST元组的插入有重要作用
typedef struct GISTInsertStack
{
BlockNumber blkno;//当前页面的块号
Buffer buffer;//当前页面所在的缓冲区
Page page;//当前页面的页号
GistNSN lsn;//用于确定是否更新或分裂
bool retry_from_parent;//如果设置该值为真,那么将拆分页面,我们需要查找目标,需要从父节点重试
OffsetNumber downlinkoffnum;//指向下行链接的偏移量
struct GISTInsertStack *parent;//指向父节点
} GISTInsertStack;
gistbuild函数
GIST建立主要使用gistbuild函数,通过分析该函数,先将主要流程总结如下:
1.初始化索引状态信息
2.根据字符串选取缓冲模式
3.初始化根页面,并申请缓冲区进行GIST的创建
4.创建临时环境
5.扫描堆元组,进行GIST的元组的插入,会调用到gistdoinsert的相关函数
6.当构建完成时,释放缓冲区和临时环境
IndexBuildResult *gistbuild(Relation heap, Relation index, IndexInfo *indexInfo)
{
IndexBuildResult *result;//声明相关的变量
double reltuples;
GISTBuildState buildstate;
Buffer buffer;
Page page;
MemoryContext oldcxt = CurrentMemoryContext;
int fillfactor;
buildstate.indexrel = index;//给buildstate数据结构中的变量赋值
buildstate.heaprel = heap;
if (index->rd_options)
{
/* 从字符串中获取缓冲模式*/
GiSTOptions *options = (GiSTOptions *) index->rd_options;
char *bufferingMode = (char *) options + options->bufferingModeOffset;
if (strcmp(bufferingMode, "on") == 0)//当bufferingmode=on时为GIST_BUFFERING_STATS
buildstate.bufferingMode = GIST_BUFFERING_STATS;
else if (strcmp(bufferingMode, "off") == 0)
buildstate.bufferingMode = GIST_BUFFERING_DISABLED;
else
buildstate.bufferingMode = GIST_BUFFERING_AUTO;
fillfactor = options->fillfactor;
}
else
{
/*
当索引太大而无法放入缓存,则切换到缓冲模式
*/
buildstate.bufferingMode = GIST_BUFFERING_AUTO;
fillfactor = GIST_DEFAULT_FILLFACTOR;
}
/* 计算页面剩余空间 */
buildstate.freespace = BLCKSZ * (100 - fillfactor) / 100;
/*
索引关系需要只调用一次,否则报错
*/
if (RelationGetNumberOfBlocks(index) != 0)
elog(ERROR, "index \"%s\" already contains data",
RelationGetRelationName(index));
buildstate.giststate = initGISTstate(index);
//创建一个临时上下文,每个元组重置处理
buildstate.giststate->tempCxt = createTempGistContext();
/* 初始化根页面*/
buffer = gistNewBuffer(index);
Assert(BufferGetBlockNumber(buffer) == GIST_ROOT_BLKNO);
page = BufferGetPage(buffer);
START_CRIT_SECTION();
//缓冲区的相关申请
GISTInitBuffer(buffer, <