Postgresql源码(107)analyze行采样流程分析(pg_class中reltuples行数评估是哪里来的准确吗)

news2024/11/23 12:06:37

总结

pg_class中reltuples行数评估是哪里来的?

  • 行数评估发生在acquire_sample_rows采样函数中,算作采样的副产品之一。

  • 总行数评估totalrows即:扫到页面中live元组的数量 / 扫到多少页面 * 总页面,向上取整。

pg_class中reltuples行数评估准确吗?

  • 小表页面数少时,随机页面选择BlockSampler_Next会选到每一个页面,所以结果是精确的。
  • 大表页面数大时,随机页面选择BlockSampler_Next会随机选择一些页面,因为采样是随机的,可以认为结果是接近准确值的。

analyze命令进入采样的前置流程

在这里插入图片描述

采样开始acquire_sample_rows

例如对100万行的表进行采样:

create table student(sno int primary key, sname varchar(10), ssex int);
insert into student select t.a, substring(md5(random()::text), 1, 5), t.a % 2 from generate_series(1, 100000) t(a);
analyze student;

进入采样函数时,准备对30000页面进行采样

  • targrows=30000

准备对30000行进行采样:

static int
acquire_sample_rows(Relation onerel, int elevel,
					HeapTuple *rows, int targrows,
					double *totalrows, double *totaldeadrows)
{
	...

获取表的页面数的准确值:5406

	totalblocks = RelationGetNumberOfBlocks(onerel);

	/* Need a cutoff xmin for HeapTupleSatisfiesVacuum */
	OldestXmin = GetOldestNonRemovableTransactionId(onerel);

	/* Prepare for sampling block numbers */
	randseed = pg_prng_uint32(&pg_global_prng_state);

初始化随机页面选取器:

  • 记录totalblocks=5406
  • 记录targrows=30000
  • 记录randseed用于生成随机数

注意函数中bs->n = samplesize;会记录30000页面数,后续BlockSampler_Next函数在生成采样页面ID时,如果页面总数小于30000,就不随机了,按顺序遍历所有页面就好了。

	nblocks = BlockSampler_Init(&bs, totalblocks, targrows, randseed);

	...
	/* Prepare for sampling rows */
	reservoir_init_selection_state(&rstate, targrows);

准备扫表

	scan = table_beginscan_analyze(onerel);
	slot = table_slot_create(onerel, NULL);
	
	...

	/* Outer loop over blocks to sample */
	while (BlockSampler_HasMore(&bs))
	{
		bool		block_accepted;

循环随机选页面targblock:

  • 页面0扫描:samplerows=185
  • 页面1扫描:samplerows=370
  • 页面5扫描:samplerows=1110

因为页面总数5406<30000,所以这里随机选择页面变成了顺序扫描所有页面。

		BlockNumber targblock = BlockSampler_Next(&bs);
		
		...

		vacuum_delay_point();

告知targblock准备scan:

		block_accepted = table_scan_analyze_next_block(scan, targblock, vac_strategy);

		/*
		 * Don't analyze if table_scan_analyze_next_block() indicated this
		 * block is unsuitable for analyzing.
		 */
		if (!block_accepted)
			continue;

内层循环,使用上面准备的scan,把当前页面内的元组都扫一遍。

		while (table_scan_analyze_next_tuple(scan, OldestXmin, &liverows, &deadrows, slot))
		{

这里扫的行数不够targrows=30000时,直接把结果记录到采样结果数组中

			if (numrows < targrows)
				rows[numrows++] = ExecCopySlotHeapTuple(slot);
			else

一旦采样数组填满了30000条,就开始使用随机算法进行替换了:

			{
				/*
				 * t in Vitter's paper is the number of records already
				 * processed.  If we need to compute a new S value, we must
				 * use the not-yet-incremented value of samplerows as t.
				 */
				if (rowstoskip < 0)
					rowstoskip = reservoir_get_next_S(&rstate, samplerows, targrows);

				if (rowstoskip <= 0)
				{
					/*
					 * Found a suitable tuple, so save it, replacing one old
					 * tuple at random
					 */
					int			k = (int) (targrows * sampler_random_fract(&rstate.randstate));

					Assert(k >= 0 && k < targrows);
					heap_freetuple(rows[k]);
					rows[k] = ExecCopySlotHeapTuple(slot);
				}

				rowstoskip -= 1;
			}

			samplerows += 1;
		}

		pgstat_progress_update_param(PROGRESS_ANALYZE_BLOCKS_DONE,
									 ++blksdone);
	}

	ExecDropSingleTupleTableSlot(slot);
	table_endscan(scan);

	/*
	 * If we didn't find as many tuples as we wanted then we're done. No sort
	 * is needed, since they're already in order.
	 *
	 * Otherwise we need to sort the collected tuples by position
	 * (itempointer). It's not worth worrying about corner cases where the
	 * tuples are already sorted.
	 */
	if (numrows == targrows)
		qsort_interruptible((void *) rows, numrows, sizeof(HeapTuple),
							compare_rows, NULL);

bs.m的含义:前面的随机页面选取器,一共选了多少个页面。
liverows的含义:被选择页面中,一共扫出来了多少个live的元组。
totalblocks的含义:表一共有多少页面。

所以总行数评估totalrows即:扫到页面中live元组的数量 / 扫到多少页面 * 总页面,向上取整。

	if (bs.m > 0)
	{
		*totalrows = floor((liverows / bs.m) * totalblocks + 0.5);
		*totaldeadrows = floor((deadrows / bs.m) * totalblocks + 0.5);
	}
	else
	{
		*totalrows = 0.0;
		*totaldeadrows = 0.0;
	}

	/*
	 * Emit some interesting relation info
	 */
	ereport(elevel,
			(errmsg("\"%s\": scanned %d of %u pages, "
					"containing %.0f live rows and %.0f dead rows; "
					"%d rows in sample, %.0f estimated total rows",
					RelationGetRelationName(onerel),
					bs.m, totalblocks,
					liverows, deadrows,
					numrows, *totalrows)));

	return numrows;
}

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

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

相关文章

十九、socket套接字编程——udp

文章目录 一、socket套接字编程接口&#xff08;一&#xff09;socket头文件&#xff08;二&#xff09;socket 常见API&#xff08;套接字编程接口&#xff09;1. 创建 socket 文件描述符 (TCP/UDP, 客户端 服务器 )2.绑定网络信息 (TCP/UDP, 服务器 )3.开始监听 socket (TCP…

【安装教程】KingFunsion3.6-Windows版本的安装教程

哈喽&#xff01;大家好&#xff0c;我是雷工&#xff01; 由于项目需要今天学习认识KingFunsion3.6及记录Windows版本的安装教程。 一、KingFunsion介绍 1、KingFunsion是什么&#xff1f; KingFunsion是一款面向工程师的管控一体化全组态平台&#xff0c;是一套面向制造企…

Flutter进阶-Future、FutureBuilder、StreamBuilder详解

一、时间循环 Event Loop机制 程序之所以卡说白了就是没有时间更新UI界面刷新屏幕导致 常见的卡顿主要是两种&#xff1a; 1.很大的计算量CPU忙不过来 2.等待&#xff0c;等服务器的响应、等用户的输入、等文件的读取...等等 在多线程的机制里每当遇到需要等的东西就开启一…

管理类联考——逻辑——知识篇——分析推理——二、匹配——haimian

匹配 题型识别 题干一般提供3-5个对象和2~3个维度的信息&#xff0c;并描述某对象及信息间的条件关系&#xff0c;要求将信息进行匹配。要从一个一个条件出发&#xff0c;通过逻辑推理&#xff0c;得出正确答案。 思维导图 解题技巧 注意选项的模式&#xff0c;如果已经将关…

Unity | HDRP高清渲染管线学习笔记:HDRP光照系统(二)

目录 一、光源类型和模式 1. Light组件 1.1 General&#xff08;通用设置&#xff09; 1.1.1 LightLayer&#xff08;光照层&#xff09; 1.2 Emission&#xff08;发光设置&#xff09; 1.3 Shadows&#xff08;阴影&#xff09; 二、Light Layer&#xff08;光源分层&…

【C/C++实战项目】扫雷游戏

目录 项目分析 外部头文件 初始化 打印 扫雷游戏函数 main函数 项目分析 游戏需要自定义地图的大小、埋雷的数量通过输入坐标进行扫雷&#xff0c;输入的坐标是埋雷的地方&#xff0c;则游戏失败输入的坐标未埋雷&#xff0c;则该坐标显示周围8个坐标总共的雷数游戏初始…

Ant Design Vue实现表格双击编辑、添加新行、文字提示

早上刚上班&#xff0c;产品就朝我工位走了过来&#xff0c;一看大事不好&#xff0c;肯定又是来提需求的&#xff01; 产品&#xff1a;做一个表格&#xff0c;要实现双击编辑的功能 我&#xff1a;做不了 产品&#xff1a;老板提的 我&#xff1a;好的&#xff0c;可以做 老板…

什么是测试开发工程师?

目录 前言&#xff1a; SDET是做啥的&#xff1f; 为什么需要测试开发&#xff1f; SDET的角色和职责 技术和软技能 非技术能力&#xff1a; 沟通能力 时间管理和组织能力 良好的工作态度 热情 日常工作 事业进阶 总结 前言&#xff1a; 测试开发工程师 (Software …

AIDL中 Binder 的具体流转过程(源码讲解)

前言 本篇文章承接上篇 Binder对象的流转&#xff08;系统服务的调用过程、AIDL的使用过程&#xff09; 上一篇简单笼统地说明了流转的大致方向与手段&#xff0c;此篇文章我们将深入代码层面&#xff0c;看看 Binder 到底是怎么实现的。 一、一个简单的AIDL示例 客户端&…

网关全局过滤器:Java中的强大工具

文章目录 网关过滤器简介网关过滤器的作用过滤器的生命周期实际应用示例权限过滤器解析 总结 网关过滤器简介 网关过滤器是一个位于应用程序和底层服务之间的组件&#xff0c;它截取进出网络请求&#xff0c;并提供对请求和响应进行处理的机制。它可以在请求到达目标服务之前或…

测试老鸟的职业生涯,从初识到功能再到自动化测试,他都经历了啥...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 张工&#xff1a;…

Qt/C++编写onvif工具(搜索/云台/预置位/OSD/录像存储)

一、前言 从最初编写这个工具开始的时间算起来&#xff0c;至少5年多&#xff0c;一直持续完善到今天&#xff0c;这个工具看起来小也不小大也不大&#xff0c;但是也是经历过无数个现场的洗礼&#xff0c;毫不夸张的说&#xff0c;市面上能够遇到的主流的厂商的设备&#xff…

深入探究 ReentrantLock 的应用和原理

博主介绍&#xff1a; ✌博主从事应用安全和大数据领域&#xff0c;有8年研发经验&#xff0c;5年面试官经验&#xff0c;Java技术专家✌ Java知识图谱点击链接&#xff1a;体系化学习Java&#xff08;Java面试专题&#xff09; &#x1f495;&#x1f495; 感兴趣的同学可以收…

微信开发者工具-导入小程序项目会自动切换到小游戏打开出错的解决方案

微信开发者工具导入小程序项目会自动切换到小游戏打开出错&#xff0c; 提示Error 提示appid错误&#xff0c;如下图 错误 Error: INVALID_TOKEN...表示网络已断开&#xff0c; 检查开发工具是否连接到网络&#xff0c; 或注销重新登录开发工具试试 提示缺少文件 如果提示缺…

智能安全用电技术电气火灾监控的应用介绍 安科瑞 许敏

摘要&#xff1a;智能安全用电技术在智慧监狱的应用&#xff0c;可以提升监狱智能化管控水平和降低能耗。文章以智能安全用电技术为入手点&#xff0c;简要分析了监狱用电现状&#xff0c;论述了智能安全用电技术在智慧监狱中的具体应用&#xff0c;对智能安全用电技术在智慧监…

【面试题12】HTTP协议三次握手和四次挥手分别是什么

文章目录 一、概览二、三次握手2.1 第一步&#xff1a;客户端向服务端发送 SYN&#xff08;同步&#xff09;包2.2 第二步&#xff1a;服务端返回 ACK&#xff08;确认&#xff09;包和 SYN 包2.3 第三步&#xff1a;客户端返回 ACK&#xff08;确认&#xff09;包 三、四次挥手…

今日分享:音频格式转换软件

小林最近特别喜欢唱歌&#xff0c;不过总是遇到一些麻烦&#xff0c;例如自己录制的音频格式无法在其他设备上播放&#xff0c;或者想把某个歌曲转成适合自己播放的格式。这时候就需要一个好用的音频格式转换器啦&#xff01;小林找了一圈&#xff0c;终于找到了几款可爱又好用…

大数据应用——工程实践III

任务一&#xff1a;完成Hadoop集群部署前环境的准备工作 1.1 虚拟机环境准备 1. 安装虚拟机 2. 克隆虚拟机 3. 修改网络配置 4. 修改主机名和映射 5. 关闭防火墙 1.2 安装JDK 1.3 安装Hadoop 1.4 集群配置 1. 编写集群分发脚本xsync 2. 集群部署规划 表 1.1 hadoop101 …

一份老网工珍藏多年的网络配置笔记

我的网工朋友大家好 俗话说得好&#xff0c;好记性不如烂笔头。 学生时代&#xff0c;我们考试前最喜欢看的就是学霸笔记&#xff0c;但工作之后&#xff0c;却没有人会愿意借给你他们的珍藏笔记了。 今天&#xff0c;想给你分享一个老网工分享在网上的精选笔记&#xff0c;…

java 8 新特性讲解Optional类--Fork/Join 框架--新时间日期API--以及接口的新特性和注解

Optional类 到目前为止&#xff0c;臭名昭著的空指针异常是导致Java应用程序失败的最常见原因。以前&#xff0c;为了解决空指针异常&#xff0c;Google公司著名的Guava项目引入了Optional类&#xff0c;Guava通过使用检查空值的方式来防止代码污染&#xff0c;它鼓励程序员写…