前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Postgresql源码(52)bitmapset分析RelationGetIndexAttrBitmap

Postgresql源码(52)bitmapset分析RelationGetIndexAttrBitmap

作者头像
mingjie
发布2022-05-31 10:04:59
3520
发布2022-05-31 10:04:59
举报
文章被收录于专栏:Postgresql源码分析

相关 《Postgresql源码(47)bitmapset原理》 《Postgresql源码(52)bitmapset分析RelationGetIndexAttrBitmap》

总结

RelationGetIndexAttrBitmap可以返回四个bitmapset标识所有索引的位置,位置全部加过偏移量(7)。

例如下面SQL有三个索引,最终返回的四个bitmapset见下面最后一行

代码语言:javascript
复制
create table t1(a int primary key, b int, c int, d int, e int);
create index idx_t1_b on t1(b);
create unique index idx_t1_d_e on t1(d,e);

          attnum       rd_indexattr   rd_keyattr     rd_pkattr   rd_idattr
t1_pkey:       1       0000100000000  0000100000000  0100000000  0100000000
idx_t1_b:      2       0001100000000  0000100000000  0100000000  0100000000
idx_t1_d_e:    4       0101100000000  0100100000000  0100000000  0100000000
               5       1101100000000  1100100000000  0100000000  0100000000   <---最后返回的四个bitmap值
  • rd_indexattr:所有索引位置,1101100000000记录了8、9、11、12,减去系统列偏移7,表示1、2、4、5列有索引。
  • rd_keyattr:唯一索引位置
  • rd_pkattr:主键索引位置
  • rd_idattr:复制标识位置,默认是主键

例子

  • 第一列a:主键
  • 第二列b:普通BTREE索引
  • 第三列c:无索引
  • 第四列d:唯一、联合索引
  • 第五列e:唯一、联合索引
代码语言:javascript
复制
drop table t1;
create table t1(a int primary key, b int, c int, d int, e int);
create index idx_t1_b on t1(b);
create unique index idx_t1_d_e on t1(d,e);

insert into t1 values (1, 100, 10, 1, 11);
insert into t1 values (2, 200, 20, 2, 22);
insert into t1 values (3, 300, 30, 3, 33);
insert into t1 values (4, 400, 40, 4, 44);
insert into t1 values (5, 500, 50, 5, 55);

-- 场景一:更新无索引列,查找项有索引
update t1 set c = 0 where a = 1;

RelationGetIndexAttrBitmap流程

attrKind = INDEX_ATTR_BITMAP_ALL

代码语言:javascript
复制
Bitmapset *
RelationGetIndexAttrBitmap(Relation relation, IndexAttrBitmapKind attrKind)
{
	Bitmapset  *indexattrs;		/* indexed columns */
	Bitmapset  *uindexattrs;	/* columns in unique indexes */
	Bitmapset  *pkindexattrs;	/* columns in the primary index */
	Bitmapset  *idindexattrs;	/* columns in the replica identity */
	List	   *indexoidlist;
	List	   *newindexoidlist;
	Oid			relpkindex;
	Oid			relreplindex;
	ListCell   *l;
	MemoryContext oldcxt;

第一次执行后rd_indexattr会填入值,后面可以直接使用

代码语言:javascript
复制
	if (relation->rd_indexattr != NULL)
	{
		switch (attrKind)
		{
			case INDEX_ATTR_BITMAP_ALL:
				return bms_copy(relation->rd_indexattr);
			case INDEX_ATTR_BITMAP_KEY:
				return bms_copy(relation->rd_keyattr);
			case INDEX_ATTR_BITMAP_PRIMARY_KEY:
				return bms_copy(relation->rd_pkattr);
			case INDEX_ATTR_BITMAP_IDENTITY_KEY:
				return bms_copy(relation->rd_idattr);
			default:
				elog(ERROR, "unknown attrKind %u", attrKind);
		}
	}
  ...

RelationGetIndexList查到三个索引的OID,用表的OID查出来的indrelid = 24759

代码语言:javascript
复制
(gdb) p indexoidlist->elements[0]->oid_value
$10 = 24762
(gdb) p indexoidlist->elements[1]->oid_value
$11 = 24764
(gdb) p indexoidlist->elements[2]->oid_value
$12 = 24765


postgres=# select indexrelid,indisprimary,indisunique,indkey from pg_index where indrelid = 24759;
 indexrelid | indisprimary | indisunique | indkey
------------+--------------+-------------+--------
      24762 | t            | t           | 1
      24764 | f            | f           | 2
      24765 | f            | t           | 4 5

RelationGetIndexList会把主键和复制索引顺便算出来

代码语言:javascript
复制
(gdb) p	relpkindex
$13 = 24762
(gdb) p	relreplindex
$14 = 24762

继续

代码语言:javascript
复制
restart:
	indexoidlist = RelationGetIndexList(relation);
  ...
	relpkindex = relation->rd_pkindex;
	relreplindex = relation->rd_replidindex;

	/*
	 * For each index, add referenced attributes to indexattrs.
	 *
	 * Note: we consider all indexes returned by RelationGetIndexList, even if
	 * they are not indisready or indisvalid.  This is important because an
	 * index for which CREATE INDEX CONCURRENTLY has just started must be
	 * included in HOT-safety decisions (see README.HOT).  If a DROP INDEX
	 * CONCURRENTLY is far enough along that we should ignore the index, it
	 * won't be returned at all by RelationGetIndexList.
	 */
	indexattrs = NULL;
	uindexattrs = NULL;
	pkindexattrs = NULL;
	idindexattrs = NULL;
	foreach(l, indexoidlist)
	{
		Oid			indexOid = lfirst_oid(l);
		Relation	indexDesc;
		Datum		datum;
		bool		isnull;
		Node	   *indexExpressions;
		Node	   *indexPredicate;
		int			i;
		bool		isKey;		/* candidate key */
		bool		isPK;		/* primary key */
		bool		isIDKey;	/* replica identity index */

检查index tuple中的配置

代码语言:javascript
复制
		indexDesc = index_open(indexOid, AccessShareLock);
		datum = heap_getattr(indexDesc->rd_indextuple, Anum_pg_index_indexprs,
							 GetPgIndexDescriptor(), &isnull);
		if (!isnull)
			indexExpressions = stringToNode(TextDatumGetCString(datum));
		else
			indexExpressions = NULL;

		datum = heap_getattr(indexDesc->rd_indextuple, Anum_pg_index_indpred,
							 GetPgIndexDescriptor(), &isnull);
		if (!isnull)
			indexPredicate = stringToNode(TextDatumGetCString(datum));
		else
			indexPredicate = NULL;

		/* Can this index be referenced by a foreign key? */
		isKey = indexDesc->rd_index->indisunique &&
			indexExpressions == NULL &&
			indexPredicate == NULL;

		/* Is this a primary key? */
		isPK = (indexOid == relpkindex);

		/* Is this index the configured (or default) replica identity? */
		isIDKey = (indexOid == relreplindex);

开始配置bitmap,三个索引每个所以都会进入下面for。

注意:配置bms_add_member的时候为什么要减去FirstLowInvalidHeapAttributeNumber?

原因:每一行的列都有6个前置系统列,所以真实的列位置需要+7

代码语言:javascript
复制
		/* Collect simple attribute references */
		for (i = 0; i < indexDesc->rd_index->indnatts; i++)
		{
			int			attrnum = indexDesc->rd_index->indkey.values[i];
			if (attrnum != 0)
			{
				indexattrs = bms_add_member(indexattrs,
											attrnum - FirstLowInvalidHeapAttributeNumber);

				if (isKey && i < indexDesc->rd_index->indnkeyatts)
					uindexattrs = bms_add_member(uindexattrs,
												 attrnum - FirstLowInvalidHeapAttributeNumber);

				if (isPK && i < indexDesc->rd_index->indnkeyatts)
					pkindexattrs = bms_add_member(pkindexattrs,
												  attrnum - FirstLowInvalidHeapAttributeNumber);

				if (isIDKey && i < indexDesc->rd_index->indnkeyatts)
					idindexattrs = bms_add_member(idindexattrs,
												  attrnum - FirstLowInvalidHeapAttributeNumber);
			}
		}
    ...
	}
...
}

对于三个索引的配置总结:

代码语言:javascript
复制
create table t1(a int primary key, b int, c int, d int, e int);
create index idx_t1_b on t1(b);
create unique index idx_t1_d_e on t1(d,e);



all      -->  indexattrs   --> relation->rd_indexattr
isKey    -->  uindexattrs  --> relation->rd_keyattr     // Can this index be referenced by a foreign key?
isPK     -->  pkindexattrs --> relation->rd_pkattr      // Is this a primary key
isIDKey  -->  idindexattrs --> relation->rd_idattr      // Is this index the configured (or default) replica identity


          attnum       rd_indexattr   rd_keyattr     rd_pkattr   rd_idattr
t1_pkey:       1       0000100000000  0000100000000  0100000000  0100000000
idx_t1_b:      2       0001100000000  0000100000000  0100000000  0100000000
idx_t1_d_e:    4       0101100000000  0100100000000  0100000000  0100000000
               5       1101100000000  1100100000000  0100000000  0100000000




-- gdb
p/t indexattrs->words[0]
p/t uindexattrs->words[0]
p/t pkindexattrs->words[0]
p/t idindexattrs->words[0]
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-05-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 总结
  • 例子
  • RelationGetIndexAttrBitmap流程
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档