searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

PostgreSQL索引浅析

2023-09-12 08:59:20
44
0

概述

       PG索引类型有Btree、Hash、GiST、GIN、SPGiST、BRIN等。支持的索引方式包括唯一索引、主键索引、多属性索引、部分索引和表达式索引。其中部分索引是对表的子集建立索引(例如一个表中id在1~100的元祖的属性建立索引)。表达式索引可建立在一个函数或表中属性计算出来的表达式上。

索引相关系统表

       索引也是表,需通过系统表进行管理。各系统表作用如下:
  • pg_am:PG支持的索引结构都存储在pg_am中。
  • pg_opclass:索引可以运用在不同数据类型的字段上,索引结构并不直接管理目标字段的类型,这些信息由pg_opclass系统表维护。pg_opclass定义索引访问方法操作符类。 
  • pg_opfamily:管理不同索引下的数据库的操作符集合。以Btree为例,共有42种opclass。其中,int2_ops、int4_ops、int8_ops三个opclass属于同一个opfamily,oid为1976。
  • pg_index:存储创建元组的部分信息,创建索引时,PG会找出每个索引列对应的opclass,并且把它们存在pg_index系统表的indclass列中。
  • pg_class:保存所有表、视图、索引等信息。每个创建的索引都会作为一个元组保存在pg_class中,可通过索引名获取其oid。
  • pg_amproc:存储具体操作符的过程函数信息,对btree来说,主要与比较和排序相关。
  • pg_amop:存储具体操作符的关联信息。因为pg_opfamily只是提供了操作符集合,具体的操作符实现存储在这里。可以看到一个操作符类包含哪些操作符,使得条件中包含这个操作符时可以使用这个索引。根据操作符左右两边的数据类型,相同的操作符也有不同的oid。
 

索引代码结构

       在PG中,索引接口被设计为上层操作函数与下层接口函数。上层操作函数统一了不同索引类型的操作。下层接口函数实现了不同索引类型对此的操作。
       索引的操作函数:每种索引类型都在pg_am中注册了操作函数,不同索引支持的操作函数的数量并不相同。
 
       
       PG索引的下层接口函数。
 
ambuild
构建索引
ambuildempty
构造空索引
aminsert
向现有索引插入新的索引元组
ambulkdelete
从索引中删除元组
amvacuumcleanup
在一次VACUUM后执行,进行额外的清理,一般用于批量删除后
amcanreturn
判断能否返回一个索引元组
amcostestimate
估算一个索引扫描的代价
amoptions
分析和验证一个索引的reloptions数组
amproperty
给出索引的字段属性
ambuildphasename
返回amproperty所属阶段
amvalidate
验证运算符类的定义
ambeginscan
开始一个新的扫描
amrescan
重新扫描
amgettuple
在给出的扫描描述符里获取下一个元组
amgetbitmap
获取索引位图
amendscan
结束扫描,释放资源
ammarkpos
标记当前扫描位置
amrestrpos
把扫描恢复到最近标记的位置
amestimateparallelscan
估算索引并行扫描运算符的大小
aminitparallelscan
初始化并行扫描
amparallelrescan
重新并行扫描
 
       以B树结构为例,btree对应的amhandler为bthandler,其中定义了B树结构索引需要实现得下层操作函数。btree索引的ambuild是btbuild,通过调用btbuild实现btree索引构建逻辑。
Datum
bthandler(PG_FUNCTION_ARGS)
{
    IndexAmRoutine *amroutine = makeNode(IndexAmRoutine);

    amroutine->amstrategies = BTMaxStrategyNumber;
    amroutine->amsupport = BTNProcs;
    amroutine->amcanorder = true;
    amroutine->amcanorderbyop = false;
    amroutine->amcanbackward = true;
    amroutine->amcanunique = true;
    amroutine->amcanmulticol = true;
    amroutine->amoptionalkey = true;
    amroutine->amsearcharray = true;
    amroutine->amsearchnulls = true;
    amroutine->amstorage = false;
    amroutine->amclusterable = true;
    amroutine->ampredlocks = true;
    amroutine->amcanparallel = true;
    amroutine->amcaninclude = true;
    amroutine->amkeytype = InvalidOid;

    amroutine->ambuild = btbuild;
    amroutine->ambuildempty = btbuildempty;
    amroutine->aminsert = btinsert;
    amroutine->ambulkdelete = btbulkdelete;
    amroutine->amvacuumcleanup = btvacuumcleanup;
    amroutine->amcanreturn = btcanreturn;
    amroutine->amcostestimate = btcostestimate;
    amroutine->amoptions = btoptions;
    amroutine->amproperty = btproperty;
    amroutine->ambuildphasename = btbuildphasename;
    amroutine->amvalidate = btvalidate;
    amroutine->ambeginscan = btbeginscan;
    amroutine->amrescan = btrescan;
    amroutine->amgettuple = btgettuple;
    amroutine->amgetbitmap = btgetbitmap;
    amroutine->amendscan = btendscan;
    amroutine->ammarkpos = btmarkpos;
    amroutine->amrestrpos = btrestrpos;
    amroutine->amestimateparallelscan = btestimateparallelscan;
    amroutine->aminitparallelscan = btinitparallelscan;
    amroutine->amparallelrescan = btparallelrescan;

    PG_RETURN_POINTER(amroutine);
}
       
       以创建索引为例,当执行“create index xxx_idx on table(xxx);”时,索引创建流程如图所示。
0条评论
0 / 1000
李****林
4文章数
0粉丝数
李****林
4 文章 | 0 粉丝
李****林
4文章数
0粉丝数
李****林
4 文章 | 0 粉丝
原创

PostgreSQL索引浅析

2023-09-12 08:59:20
44
0

概述

       PG索引类型有Btree、Hash、GiST、GIN、SPGiST、BRIN等。支持的索引方式包括唯一索引、主键索引、多属性索引、部分索引和表达式索引。其中部分索引是对表的子集建立索引(例如一个表中id在1~100的元祖的属性建立索引)。表达式索引可建立在一个函数或表中属性计算出来的表达式上。

索引相关系统表

       索引也是表,需通过系统表进行管理。各系统表作用如下:
  • pg_am:PG支持的索引结构都存储在pg_am中。
  • pg_opclass:索引可以运用在不同数据类型的字段上,索引结构并不直接管理目标字段的类型,这些信息由pg_opclass系统表维护。pg_opclass定义索引访问方法操作符类。 
  • pg_opfamily:管理不同索引下的数据库的操作符集合。以Btree为例,共有42种opclass。其中,int2_ops、int4_ops、int8_ops三个opclass属于同一个opfamily,oid为1976。
  • pg_index:存储创建元组的部分信息,创建索引时,PG会找出每个索引列对应的opclass,并且把它们存在pg_index系统表的indclass列中。
  • pg_class:保存所有表、视图、索引等信息。每个创建的索引都会作为一个元组保存在pg_class中,可通过索引名获取其oid。
  • pg_amproc:存储具体操作符的过程函数信息,对btree来说,主要与比较和排序相关。
  • pg_amop:存储具体操作符的关联信息。因为pg_opfamily只是提供了操作符集合,具体的操作符实现存储在这里。可以看到一个操作符类包含哪些操作符,使得条件中包含这个操作符时可以使用这个索引。根据操作符左右两边的数据类型,相同的操作符也有不同的oid。
 

索引代码结构

       在PG中,索引接口被设计为上层操作函数与下层接口函数。上层操作函数统一了不同索引类型的操作。下层接口函数实现了不同索引类型对此的操作。
       索引的操作函数:每种索引类型都在pg_am中注册了操作函数,不同索引支持的操作函数的数量并不相同。
 
       
       PG索引的下层接口函数。
 
ambuild
构建索引
ambuildempty
构造空索引
aminsert
向现有索引插入新的索引元组
ambulkdelete
从索引中删除元组
amvacuumcleanup
在一次VACUUM后执行,进行额外的清理,一般用于批量删除后
amcanreturn
判断能否返回一个索引元组
amcostestimate
估算一个索引扫描的代价
amoptions
分析和验证一个索引的reloptions数组
amproperty
给出索引的字段属性
ambuildphasename
返回amproperty所属阶段
amvalidate
验证运算符类的定义
ambeginscan
开始一个新的扫描
amrescan
重新扫描
amgettuple
在给出的扫描描述符里获取下一个元组
amgetbitmap
获取索引位图
amendscan
结束扫描,释放资源
ammarkpos
标记当前扫描位置
amrestrpos
把扫描恢复到最近标记的位置
amestimateparallelscan
估算索引并行扫描运算符的大小
aminitparallelscan
初始化并行扫描
amparallelrescan
重新并行扫描
 
       以B树结构为例,btree对应的amhandler为bthandler,其中定义了B树结构索引需要实现得下层操作函数。btree索引的ambuild是btbuild,通过调用btbuild实现btree索引构建逻辑。
Datum
bthandler(PG_FUNCTION_ARGS)
{
    IndexAmRoutine *amroutine = makeNode(IndexAmRoutine);

    amroutine->amstrategies = BTMaxStrategyNumber;
    amroutine->amsupport = BTNProcs;
    amroutine->amcanorder = true;
    amroutine->amcanorderbyop = false;
    amroutine->amcanbackward = true;
    amroutine->amcanunique = true;
    amroutine->amcanmulticol = true;
    amroutine->amoptionalkey = true;
    amroutine->amsearcharray = true;
    amroutine->amsearchnulls = true;
    amroutine->amstorage = false;
    amroutine->amclusterable = true;
    amroutine->ampredlocks = true;
    amroutine->amcanparallel = true;
    amroutine->amcaninclude = true;
    amroutine->amkeytype = InvalidOid;

    amroutine->ambuild = btbuild;
    amroutine->ambuildempty = btbuildempty;
    amroutine->aminsert = btinsert;
    amroutine->ambulkdelete = btbulkdelete;
    amroutine->amvacuumcleanup = btvacuumcleanup;
    amroutine->amcanreturn = btcanreturn;
    amroutine->amcostestimate = btcostestimate;
    amroutine->amoptions = btoptions;
    amroutine->amproperty = btproperty;
    amroutine->ambuildphasename = btbuildphasename;
    amroutine->amvalidate = btvalidate;
    amroutine->ambeginscan = btbeginscan;
    amroutine->amrescan = btrescan;
    amroutine->amgettuple = btgettuple;
    amroutine->amgetbitmap = btgetbitmap;
    amroutine->amendscan = btendscan;
    amroutine->ammarkpos = btmarkpos;
    amroutine->amrestrpos = btrestrpos;
    amroutine->amestimateparallelscan = btestimateparallelscan;
    amroutine->aminitparallelscan = btinitparallelscan;
    amroutine->amparallelrescan = btparallelrescan;

    PG_RETURN_POINTER(amroutine);
}
       
       以创建索引为例,当执行“create index xxx_idx on table(xxx);”时,索引创建流程如图所示。
文章来自个人专栏
PG学习
4 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0