postgres源码解析41 btree索引文件的创建--2

news2024/12/24 0:27:56

本文将从btbuild函数作为入口从源码角度进行讲解btree文件的创建流程,执行SQL对应为CREATE TABLE wp_shy(id int primary key, name carchar(20))。知识回顾见:postgres源码解析41 btree索引文件的创建–1

执行流程图梳理

在这里插入图片描述

_bt_spools_heapscan 执行流程

1)首先定义并初始化BTBuildState结构体;
2)如果允许并行模式,则调用 _bt_begin_parallel 创建 parallel context上下文,并启动工作线程;
3)调用 tuplesort_begin_index_btree 构建 Tuplesortstate结构体,该结构体记录元组排序转态的关键信息;
存放目标扫描的元组数组,对应数据类型的比较函数,索引和扫描键信息,
4)如果该索引为唯一索引,则需构造spools2结构用以存放死堆表元组对应的索引元组,便利之处在于这些索引均不是最新的,对于唯一索引来就无须检查这些元组是否唯一,可以直接插入索引结构中。
5)上述步骤完成后,将 spools2 空间释放

/*
 * Create and initialize one or two spool structures, and save them in caller's
 * buildstate argument.  May also fill-in fields within indexInfo used by index
 * builds.
 *
 * Scans the heap, possibly in parallel, filling spools with IndexTuples.  This
 * routine encapsulates all aspects of managing parallelism.  Caller need only
 * call _bt_end_parallel() in parallel case after it is done with spool/spool2.
 *
 * Returns the total number of heap tuples scanned.
 */
static double
_bt_spools_heapscan(Relation heap, Relation index, BTBuildState *buildstate,
					IndexInfo *indexInfo)
{
	BTSpool    *btspool = (BTSpool *) palloc0(sizeof(BTSpool));
	SortCoordinate coordinate = NULL;
	double		reltuples = 0;

	/*
	 * We size the sort area as maintenance_work_mem rather than work_mem to
	 * speed index creation.  This should be OK since a single backend can't
	 * run multiple index creations in parallel (see also: notes on
	 * parallelism and maintenance_work_mem below).
	 */
	btspool->heap = heap;
	btspool->index = index;
	btspool->isunique = indexInfo->ii_Unique;
	btspool->nulls_not_distinct = indexInfo->ii_NullsNotDistinct;

	/* Save as primary spool */
	buildstate->spool = btspool;

	/* Report table scan phase started */
	pgstat_progress_update_param(PROGRESS_CREATEIDX_SUBPHASE,
								 PROGRESS_BTREE_PHASE_INDEXBUILD_TABLESCAN);

	/* Attempt to launch parallel worker scan when required */
	if (indexInfo->ii_ParallelWorkers > 0)
		_bt_begin_parallel(buildstate, indexInfo->ii_Concurrent,
						   indexInfo->ii_ParallelWorkers);

	/*
	 * If parallel build requested and at least one worker process was
	 * successfully launched, set up coordination state
	 */
	if (buildstate->btleader)
	{
		coordinate = (SortCoordinate) palloc0(sizeof(SortCoordinateData));
		coordinate->isWorker = false;
		coordinate->nParticipants =
			buildstate->btleader->nparticipanttuplesorts;
		coordinate->sharedsort = buildstate->btleader->sharedsort;
	}

	/*
	 * Begin serial/leader tuplesort.
	 *
	 * In cases where parallelism is involved, the leader receives the same
	 * share of maintenance_work_mem as a serial sort (it is generally treated
	 * in the same way as a serial sort once we return).  Parallel worker
	 * Tuplesortstates will have received only a fraction of
	 * maintenance_work_mem, though.
	 *
	 * We rely on the lifetime of the Leader Tuplesortstate almost not
	 * overlapping with any worker Tuplesortstate's lifetime.  There may be
	 * some small overlap, but that's okay because we rely on leader
	 * Tuplesortstate only allocating a small, fixed amount of memory here.
	 * When its tuplesort_performsort() is called (by our caller), and
	 * significant amounts of memory are likely to be used, all workers must
	 * have already freed almost all memory held by their Tuplesortstates
	 * (they are about to go away completely, too).  The overall effect is
	 * that maintenance_work_mem always represents an absolute high watermark
	 * on the amount of memory used by a CREATE INDEX operation, regardless of
	 * the use of parallelism or any other factor.
	 */
	buildstate->spool->sortstate =
		tuplesort_begin_index_btree(heap, index, buildstate->isunique,
									buildstate->nulls_not_distinct,
									maintenance_work_mem, coordinate,
									TUPLESORT_NONE);

	/*
	 * If building a unique index, put dead tuples in a second spool to keep
	 * them out of the uniqueness check.  We expect that the second spool (for
	 * dead tuples) won't get very full, so we give it only work_mem.
	 */
	if (indexInfo->ii_Unique)
	{
		BTSpool    *btspool2 = (BTSpool *) palloc0(sizeof(BTSpool));
		SortCoordinate coordinate2 = NULL;

		/* Initialize secondary spool */
		btspool2->heap = heap;
		btspool2->index = index;
		btspool2->isunique = false;
		/* Save as secondary spool */
		buildstate->spool2 = btspool2;

		if (buildstate->btleader)
		{
			/*
			 * Set up non-private state that is passed to
			 * tuplesort_begin_index_btree() about the basic high level
			 * coordination of a parallel sort.
			 */
			coordinate2 = (SortCoordinate) palloc0(sizeof(SortCoordinateData));
			coordinate2->isWorker = false;
			coordinate2->nParticipants =
				buildstate->btleader->nparticipanttuplesorts;
			coordinate2->sharedsort = buildstate->btleader->sharedsort2;
		}

		/*
		 * We expect that the second one (for dead tuples) won't get very
		 * full, so we give it only work_mem
		 */
		buildstate->spool2->sortstate =
			tuplesort_begin_index_btree(heap, index, false, false, work_mem,
										coordinate2, TUPLESORT_NONE);
	}

	/* Fill spool using either serial or parallel heap scan */
	if (!buildstate->btleader)
		reltuples = table_index_build_scan(heap, index, indexInfo, true, true,
										   _bt_build_callback, (void *) buildstate,
										   NULL);
	else
		reltuples = _bt_parallel_heapscan(buildstate,
										  &indexInfo->ii_BrokenHotChain);

	/*
	 * Set the progress target for the next phase.  Reset the block number
	 * values set by table_index_build_scan
	 */
	{
		const int	progress_index[] = {
			PROGRESS_CREATEIDX_TUPLES_TOTAL,
			PROGRESS_SCAN_BLOCKS_TOTAL,
			PROGRESS_SCAN_BLOCKS_DONE
		};
		const int64 progress_vals[] = {
			buildstate->indtuples,
			0, 0
		};

		pgstat_progress_update_multi_param(3, progress_index, progress_vals);
	}

	/* okay, all heap tuples are spooled */
	if (buildstate->spool2 && !buildstate->havedead)
	{
		/* spool2 turns out to be unnecessary */
		_bt_spooldestroy(buildstate->spool2);
		buildstate->spool2 = NULL;
	}

	return reltuples;
}

_bt_leafbuild 执行流程

该函数的主要功能是将_bt_spools_heapscan扫描的索引元组(位于BTBuildState结构体中的 spool/spool2数据类型,该类型是一个数组,每个元素为索引元组)插入叶子结点中,如果叶子不存在,则会新建。
在这里插入图片描述
执行流程
1 调用 tuplesort_performsort对spool/spool2存放的索引元组进行排序(单独进行);
2 构建并初始化 BTWriteState结构体信息;
3 调用 _bt_load 函数将spool与spool2中的元组进行合并排序,将其填充至btree叶子节点中;
    _bt_load 函数的工作流程如图:
   1)根据入参初始化 BTPageState结构体
   2)循环遍历spool/spool2中的元组,如果spool2为空,则直接调用_bt_buildadd将spool中的元组插入索引叶子结点中,反 之会先调用相应的排序函数确定两者的偏序关系,在调用_bt_buildadd函数进行上述插入操作;
   3)紧接着完善叶子节点与父节点的link关系,并写入元页信息,同时记录WAL日志,该操作由_bt_uppershutdown函数完成;
   4)将生成的索引页持久化至磁盘中,目的是防止发生崩溃重启时重放不了检查点之前的日志条目。[因为此相关的WAL日志只是在WAL buffer中构建好,并没有刷盘(未调用XLOGFlush),假设检查点发生时此日志条目落盘,但是对应的索引页却未持久化(索引页是在进程的私有内存中构建的)],如发生奔溃;此后重启根据检查点的规则便不会去回放WAL日志条目。

_bt_buildadd 工作流程

该函数的功能是将指定的索引元组插入到索引页结构中,在索引页结构空间不足时,会申请一个页面作为它的右兄弟,继续插入操作,最后会更新兄弟或者父子关系。
在这里插入图片描述

  1. 首先检查索引元组大小是否超过索引页大小的1/3,若超过则打印出错信息,反之转至步骤2;
    2)如果当前页能够容纳所要插入的元组,则转至步骤 6;
    3)将当前页面置为opage,申请一个新页面为npage,将opage最大的索引last_off元组复制到npage中,后续经整理使其成为oage的Highkey
  2. 紧接着通过BTPagestate.btps_next判断是否有父节点,若没有则创建一个父节点,并将opage中的min key复制到父节点中,更新opage与npage间的链接关系;
    5)此时旧页opage已经完成填充不会再修改,此后调用 _bt_blwritepage将opage写入索引文件;
    6)最后将带插入元祖添加至当前页,并更新BTPageState结构信息。

_bt_uppershutdown执行流程

该函数的主要功能是将完成的btree进行持久化,在此过程会更新父子页的链接关系

在这里插入图片描述

/*
 * Finish writing out the completed btree.
 */
static void
_bt_uppershutdown(BTWriteState *wstate, BTPageState *state)
{
	BTPageState *s;
	BlockNumber rootblkno = P_NONE;
	uint32		rootlevel = 0;
	Page		metapage;

	/*
	 * Each iteration of this loop completes one more level of the tree.
	 */
	for (s = state; s != NULL; s = s->btps_next)
	{
		BlockNumber blkno;
		BTPageOpaque opaque;

		blkno = s->btps_blkno;
		opaque = BTPageGetOpaque(s->btps_page);

		/*
		 * We have to link the last page on this level to somewhere.
		 *
		 * If we're at the top, it's the root, so attach it to the metapage.
		 * Otherwise, add an entry for it to its parent using its low key.
		 * This may cause the last page of the parent level to split, but
		 * that's not a problem -- we haven't gotten to it yet.
		 */
		if (s->btps_next == NULL)
		{
			opaque->btpo_flags |= BTP_ROOT;
			rootblkno = blkno;
			rootlevel = s->btps_level;
		}
		else
		{
			Assert((BTreeTupleGetNAtts(s->btps_lowkey, wstate->index) <=
					IndexRelationGetNumberOfKeyAttributes(wstate->index) &&
					BTreeTupleGetNAtts(s->btps_lowkey, wstate->index) > 0) ||
				   P_LEFTMOST(opaque));
			Assert(BTreeTupleGetNAtts(s->btps_lowkey, wstate->index) == 0 ||
				   !P_LEFTMOST(opaque));
			BTreeTupleSetDownLink(s->btps_lowkey, blkno);
			_bt_buildadd(wstate, s->btps_next, s->btps_lowkey, 0);
			pfree(s->btps_lowkey);
			s->btps_lowkey = NULL;
		}

		/*
		 * This is the rightmost page, so the ItemId array needs to be slid
		 * back one slot.  Then we can dump out the page.
		 */
		_bt_slideleft(s->btps_page);
		_bt_blwritepage(wstate, s->btps_page, s->btps_blkno);
		s->btps_page = NULL;	/* writepage freed the workspace */
	}

	/*
	 * As the last step in the process, construct the metapage and make it
	 * point to the new root (unless we had no data at all, in which case it's
	 * set to point to "P_NONE").  This changes the index to the "valid" state
	 * by filling in a valid magic number in the metapage.
	 */
	metapage = (Page) palloc(BLCKSZ);
	_bt_initmetapage(metapage, rootblkno, rootlevel,
					 wstate->inskey->allequalimage);
	_bt_blwritepage(wstate, metapage, BTREE_METAPAGE);
}

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

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

相关文章

2153年,人类已被AI所奴役。就在这一天,作为一名被俘虏的“搜查部队”士兵,你来到了A0007号城外的反抗军基地中

2153年&#xff0c;地球。   人类&#xff0c;已被AI所奴役。   这个AI的缩写名为——PTA&#xff0c;或称“辟塔”。      辟塔的原型&#xff0c;是一个用于分析网络用户消费倾向并立即给出相关引导的软广告程序。   很快&#xff0c;辟塔便成了广大商家的宠儿&…

【华为上机真题 2022】求解连续数列

&#x1f388; 作者&#xff1a;Linux猿 &#x1f388; 简介&#xff1a;CSDN博客专家&#x1f3c6;&#xff0c;华为云享专家&#x1f3c6;&#xff0c;Linux、C/C、云计算、物联网、面试、刷题、算法尽管咨询我&#xff0c;关注我&#xff0c;有问题私聊&#xff01; &…

MatLab SimuLink国产代替

MATLab SimuLink国产代替 米国的限制&#xff0c;把工业软件的国产化推到风口浪尖&#xff0c;作为扎根工业软件开源基础架构20多年的UCanCode, 一直是国外顶尖工业软件的基础架构提供商之一。许多国外软件都在这个基础上构建出来&#xff0c;这里我们也希望探讨一下国产代替Ma…

乐享元游的 UWA Pipeline 最佳实践分享

“躬身入局 践行游戏研发工业化”是UWA在2022年研发上坚持的方向&#xff0c;其中UWA Pipeline更是今年在工业化部署上的一个重要的突破口。在近一年里&#xff0c;越来越多的游戏研发团队在日常项目生产开发中&#xff0c;使用UWA Pipeline搭建了符合自身需求的DevOps研发交付…

fat32文件系统分析

fat32文件系统结构&#xff1a; fat32文件系统比fat16文件系统少了根目录FDT&#xff0c;其实是将根目录归结到数据区中了。 注意数据区第一个扇区所在蔟为2号蔟。 首先在磁盘管理中创建一个fat32磁盘&#xff1a; 大小为16GB。 使用winhex打开磁盘。 可以看到MBR在扇区0处…

AI推理卡/tensorRT c++

#####AI 推理卡&#xff1a;我的需求是x86上Nvidia显卡训练好的模型 用在AI推理卡上进行推理### AI 推理卡 环境配置 安装ubuntu系统、AI推理卡环境 1&#xff0c;安装ubuntu20.04.4 过程忽略&#xff0c;网上教程很多。 2&#xff0c;ubuntu20.04.4设置root登录&#xf…

入门系列 - Git基本操作

本篇文章&#xff0c;是基于我自用Linux系统中的自定义文件夹“test_rep”&#xff0c;当做示例演示 具体Git仓库的目录在&#xff1a;/usr/local/git/test_rep Git基本操作 之前我们已经创建了 Git 版本库了&#xff0c;下一步我们将进行一些 Git 的基本操作。 有关 Git 版本…

微服务框架 SpringCloud微服务架构 28 数据同步 28.3 声明队列和交换机

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 SpringCloud微服务架构 文章目录微服务框架SpringCloud微服务架构28 数据同步28.3 声明队列和交换机28.3.1 直接开干28 数据同步 28.3 声明…

【Mybatis】一级缓存和二级缓存

【Mybatis】一级缓存和二级缓存&#xff08;一&#xff09;为什么需要缓存&#xff08;二&#xff09;一级缓存&#xff08;在SqlSession上缓存&#xff09;【1】示例代码【2】增删改操作会刷新一级缓存【3】一级缓存流程总结&#xff08;1&#xff09;一级缓存简介&#xff08…

多点DMALL冲刺港股:年亏损超9亿 腾讯IDG金蝶是股东

雷递网 雷建平 12月8日多点数智有限公司&#xff08;简称&#xff1a;“多点数智”&#xff09;日前递交招股书&#xff0c;准备在港交所上市。年亏损超9亿多点DMALL成立于2015年&#xff0c;为本地零售业提供基于云的一站式端到端的数字零售SaaS平台。多点DMALL提供的服务包括…

搜索是过拟合的生成;生成是欠拟合的搜索

神经搜索的最大竞争者可能来自于一种甚至不需要向量嵌入作为中间表示的技术 —— 一种直接返回你想要的结果的端到端技术。"那么&#xff0c;谁将是神经搜索最大的竞争对手&#xff1f;"本文作者&#xff1a;肖涵&#xff0c;Jina AI 创始人兼 CEO 谁将是神经搜索最大…

Redis框架(二):SpringDataRedis入门和序列化方式解决内存占用问题

SpringDataRedis入门和序列化方式解决内存占用问题基本介绍实例Demo自定义RedisTemplate序列化自定义的RestTemplate的内存占用问题StringRedisTemplate解决内存占用问题总结SpringCloud章节复习已经过去&#xff0c;新的章节Redis开始了&#xff0c;这个章节中将会回顾Redis 主…

c#入门-可选参数,不定长参数

可选参数 声明可选参数 函数的参数在声明时&#xff0c;可以同时为其赋值一个常量。 但是所有这样的参数&#xff0c;需要在所有必填参数的后面。 void Any(int i 10) {Console.WriteLine(i); }使用可选参数 稍后&#xff0c;在调用函数时&#xff0c;你可以不填可选参数。…

1 - 线程池的基础用法

参考&#xff1a;线程池的基本用法 - 简书 1、为什么要用线程池&#xff1f; 在java中&#xff0c;开启线程的方式一般分为以下三种&#xff1a; a. 继承Thread&#xff0c;实现其run方法&#xff1b; b. 实现Runnabler接口&#xff0c;通过Thread来实现线程&#xff1b; …

法的概念与大纲

一、法的概念 法是由国家制定或认可并由国家强制力保证实施的&#xff0c;反映特定物质生活条件所决定的统治阶级意志&#xff0c;以权利和义务为内容&#xff0c;以确认、保护和发展对统治阶级有利的社会关系和社会秩序为目的的规范系统。 二、法的特征 规范性 国家意志性 权…

微信恢复大师花了200多,套路一环接一环!

数据恢复本是一个科技进步的体现&#xff0c;让误操作导致的重要数据可以找回来。但是近年来数据恢复跟诈骗挂钩&#xff0c;数据恢复本是利好的事情&#xff0c;为什么会跟诈骗挂钩。究竟是什么原因呢&#xff1f;最近小编发现&#xff0c;百度推荐词出现&#xff1a;“微信恢…

Neural Network-神经网络算法本质

1. Word2vec~single CBOW算法推导BP word2vec主要实现方式有&#xff1a;skip-gram和CBOW。 CBOW的目的是根据上下文contextual words来预测当前中心词的概率&#xff0c;且上下文所有单词对当前中心词出现的概率影响权重是一样的&#xff0c;如在袋子中取词&#xff0c;取出…

痞子衡嵌入式:国内外串行NOR Flash厂商官网Cross Reference功能使用体验

大家好&#xff0c;我是痞子衡&#xff0c;是正经搞技术的痞子。今天痞子衡给大家讲的是国内外串行NOR Flash厂商官网Cross Reference功能。 串行 NOR Flash 是一个相对发展稳定的市场&#xff0c;目前全球市场约 90% 的份额被中国的三家厂商(Winbond华邦/MXIC旺宏/GigaDevice兆…

Java入门教程(26)——继承

文章目录1.继承的作用2.继承的关键字3.继承的特点4.实例5.instanceof 运算符继承是面向对象三大特征之一&#xff0c;继承可以让我们减少代码量&#xff0c;实现类的复用1.继承的作用 代码复用&#xff0c;更加容易实现类的扩展方便建模 2.继承的关键字 extends&#xff0c;…

网站都变灰了,几行代码可以实现

前言 这两天&#xff0c;我们经常逛的好多网站、app首页都变灰了&#xff0c;原因大家应该都知道了 网站变灰 ①B站 ②爱奇艺 ③ 腾讯视频 ④ csdn ⑤百度 怎么实现的呢&#xff1f; 难道这些网站开发商在网站开发的时候都准备一套灰色主题的UI么&#xff1f; 好奇心…