PostgreSQL数据库TableAM——Table scan callbacks

news2024/12/24 8:15:16

在这里插入图片描述

TableAM Table scan

TableAM提供了如下4个接口用于实现表数据的扫描功能。scan_begin函数的形参nkeys不为零,则扫描结果需要根据scan keys先进行过滤;pscan如果不为null,说明该结构体已经由parallelscan_initialize初始化过了(仅仅在table_beginscan_parallel函数中出现这种情况)。scan_begin函数返回的时后续函数都需要的TableScanDesc结构体,该结构体可以看成’父类’,实现不同的TableAM,将TableScanDesc结构体作为其第一个成员,再添加TableAM自定义的成员,从而实现’子类’。scan_getnextslot函数用于返回下一个元组,并存储在形参slot中。

	/* ------------------------------------------------------------------------
	 * Table scan callbacks.
	 * ------------------------------------------------------------------------
	 */
	/* Start a scan of `rel`.  The callback has to return a TableScanDesc, which will typically be embedded in a larger, AM specific, struct. If nkeys != 0, the results need to be filtered by those scan keys. pscan, if not NULL, will have already been initialized with parallelscan_initialize(), and has to be for the same relation. Will only be set coming from table_beginscan_parallel().
	 * `flags` is a bitmask indicating the type of scan (ScanOptions's SO_TYPE_*, currently only one may be specified), options controlling the scan's behaviour (ScanOptions's SO_ALLOW_*, several may be specified, an AM may ignore unsupported ones) and whether the snapshot needs to be deallocated at scan_end (ScanOptions's SO_TEMP_SNAPSHOT). */
	TableScanDesc (*scan_begin) (Relation rel, Snapshot snapshot, int nkeys, struct ScanKeyData *key, ParallelTableScanDesc pscan, uint32 flags);
	/* Release resources and deallocate scan. If TableScanDesc.temp_snap, TableScanDesc.rs_snapshot needs to be unregistered. */
	void		(*scan_end) (TableScanDesc scan);
	/* Restart relation scan.  If set_params is set to true, allow_{strat, sync, pagemode} (see scan_begin) changes should be taken into account. */
	void		(*scan_rescan) (TableScanDesc scan, struct ScanKeyData *key, bool set_params, bool allow_strat, bool allow_sync, bool allow_pagemode);
	/* Return next tuple from `scan`, store in slot. */
	bool		(*scan_getnextslot) (TableScanDesc scan, ScanDirection direction, TupleTableSlot *slot);

scan_begin

ScanOptions枚举类型用于向scan_begin函数中传入控制scan行为的掩码,SO_TYPE_*用于指明扫描的类型,SO_ALLOW_STRAT用于指明是否使用access strategy访问缓冲区shared buffer,SO_ALLOW_SYNC指明是否向syncscan逻辑汇报位置,SO_ALLOW_PAGEMODE用于指明每次一页检查可见性。

/* Bitmask values for the flags argument to the scan_begin callback. */
typedef enum ScanOptions{
	/* one of SO_TYPE_* may be specified */
	SO_TYPE_SEQSCAN = 1 << 0, SO_TYPE_BITMAPSCAN = 1 << 1, SO_TYPE_SAMPLESCAN = 1 << 2, SO_TYPE_ANALYZE = 1 << 3, SO_TYPE_TIDSCAN = 1 << 8,

	/* several of SO_ALLOW_* may be specified */	
	SO_ALLOW_STRAT = 1 << 4, /* allow or disallow use of access strategy */	 
	SO_ALLOW_SYNC = 1 << 5, /* report location to syncscan logic? */ 	
	SO_ALLOW_PAGEMODE = 1 << 6, /* verify visibility page-at-a-time? */

	/* unregister snapshot at scan end? */
	SO_TEMP_SNAPSHOT = 1 << 7 
} ScanOptions;

table_beginscan和table_beginscan_parallel用于执行SEQSCAN,返回经快照检查可见性的元组。在src/backend/executor/nodeSeqscan.c文件中的SeqNext函数会调用table_beginscan函数,如果scan为非并行,或计划并行实现确实顺序执行时,第一次进入该函数需要调用table_beginscan生成并初始化TableScanDesc函数。table_beginscan_parallel函数由执行器调用,其流程是如果由快照被序列化到共享内存中,则将快照恢复并Register,增加SO_TEMP_SNAPSHOT(scan完成后endscan Unregister该快照);否则使用调用者传入的SNAPSHOT_ANY(Any tuple is visible)。最后调用TableAM自定义的scan_begin接口。该函数在PostgreSQL数据库TableAM——HeapAM Parallel table scan已经介绍过了。用于在并行scan时替换table_beginscan函数使用。

/* Start a scan of `rel`. Returned tuples pass a visibility test of `snapshot`, and if nkeys != 0, the results are filtered by those scan keys. */
static inline TableScanDesc table_beginscan(Relation rel, Snapshot snapshot, int nkeys, struct ScanKeyData *key) {
	uint32		flags = SO_TYPE_SEQSCAN | SO_ALLOW_STRAT | SO_ALLOW_SYNC | SO_ALLOW_PAGEMODE;
	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
}

table_beginscan_strat函数相对于table_beginscan多了两个形参用于控制access strategy使用和是否向syncscan逻辑汇报位置。

/* Like table_beginscan(), but table_beginscan_strat() offers an extended API that lets the caller control whether a nondefault buffer access strategy can be used, and whether syncscan can be chosen (possibly resulting in the scan not starting from block zero).  Both of these default to true with plain table_beginscan. */
static inline TableScanDesc table_beginscan_strat(Relation rel, Snapshot snapshot, int nkeys, struct ScanKeyData *key, bool allow_strat, bool allow_sync){
	uint32		flags = SO_TYPE_SEQSCAN | SO_ALLOW_PAGEMODE;
	if (allow_strat) flags |= SO_ALLOW_STRAT;
	if (allow_sync) flags |= SO_ALLOW_SYNC;
	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
}

table_beginscan_bm函数用于BITMAPSCAN,table_beginscan_bm是为位图堆扫描设置TableScanDesc的另一个入口点。尽管这种扫描技术确实与标准的seqscan非常不同,但有足够的通用性,因此值得使用相同的数据结构。

/* table_beginscan_bm is an alternative entry point for setting up a TableScanDesc for a bitmap heap scan.  Although that scan technology is really quite unlike a standard seqscan, there is just enough commonality to make it worth using the same data structure. */
static inline TableScanDesc table_beginscan_bm(Relation rel, Snapshot snapshot, int nkeys, struct ScanKeyData *key){
	uint32		flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
}

table_beginscan_sampling是为TABLESAMPLE扫描设置TableScanDesc的另一个入口点。与位图扫描一样,使用相同的数据结构是值得的,尽管行为有所不同。除了table_beginscan_strat提供的选项外,此调用还允许控制是否使用页面模式可见性检查。

/* table_beginscan_sampling is an alternative entry point for setting up a TableScanDesc for a TABLESAMPLE scan.  As with bitmap scans, it's worth using the same data structure although the behavior is rather different. In addition to the options offered by table_beginscan_strat, this call also allows control of whether page-mode visibility checking is used. */
static inline TableScanDesc table_beginscan_sampling(Relation rel, Snapshot snapshot, int nkeys, struct ScanKeyData *key, bool allow_strat, bool allow_sync, bool allow_pagemode){
	uint32		flags = SO_TYPE_SAMPLESCAN;
	if (allow_strat) flags |= SO_ALLOW_STRAT;
	if (allow_sync) flags |= SO_ALLOW_SYNC;
	if (allow_pagemode) flags |= SO_ALLOW_PAGEMODE;
	return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
}

table_beginscan_tid是为tid扫描设置TableScanDesc的另一个入口点。与位图扫描一样,使用相同的数据结构是值得的,尽管行为有所不同。

/* table_beginscan_tid is an alternative entry point for setting up a TableScanDesc for a Tid scan. As with bitmap scans, it's worth using the same data structure although the behavior is rather different. */
static inline TableScanDesc table_beginscan_tid(Relation rel, Snapshot snapshot) {
	uint32		flags = SO_TYPE_TIDSCAN;
	return rel->rd_tableam->scan_begin(rel, snapshot, 0, NULL, NULL, flags);
}

table_beginscan_analyze是为analyze扫描设置TableScanDesc的另一个入口点。与位图扫描一样,使用相同的数据结构是值得的,尽管行为有所不同。

/* table_beginscan_analyze is an alternative entry point for setting up a TableScanDesc for an ANALYZE scan.  As with bitmap scans, it's worth using the same data structure although the behavior is rather different. */
static inline TableScanDesc table_beginscan_analyze(Relation rel) {
	uint32		flags = SO_TYPE_ANALYZE;
	return rel->rd_tableam->scan_begin(rel, NULL, 0, NULL, NULL, flags);
}

table_beginscan_catalog是为扫描系统表而提供的函数。该函数在src/backend/bootstrap/bootstrap.c、src/backend/catalog/aclchk.c等文件中都有调用。

TableScanDesc table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key) {
	uint32		flags = SO_TYPE_SEQSCAN | SO_ALLOW_STRAT | SO_ALLOW_SYNC | SO_ALLOW_PAGEMODE | SO_TEMP_SNAPSHOT;
	Oid			relid = RelationGetRelid(relation);
	Snapshot	snapshot = RegisterSnapshot(GetCatalogSnapshot(relid));
	return relation->rd_tableam->scan_begin(relation, snapshot, nkeys, key, NULL, flags);
}

scan_rescan

table_rescan和table_rescan_set_params函数都用于重启表的扫描。不同之处在于table_rescan_set_params允许在开始新扫描之前更改缓冲区策略、同步扫描和页面模式选项。注意,尽管syncscan的实际使用可能会发生变化(有效地,启用或禁用报告),但之前选择的startblock将被保留。在src/backend/executor/nodeSeqscan.c文件中的ExecReScanSeqScan函数中会调用。

/* Restart a relation scan. */
static inline void table_rescan(TableScanDesc scan, struct ScanKeyData *key){
	scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
}
/* Restart a relation scan after changing params.
 * This call allows changing the buffer strategy, syncscan, and pagemode options before starting a fresh scan.  Note that although the actual use of syncscan might change (effectively, enabling or disabling reporting), the previously selected startblock will be kept. */
static inline void table_rescan_set_params(TableScanDesc scan, struct ScanKeyData *key, bool allow_strat, bool allow_sync, bool allow_pagemode){
	scan->rs_rd->rd_tableam->scan_rescan(scan, key, true,allow_strat, allow_sync, allow_pagemode);
}

scan_getnextslot

table_scan_getnextslot函数用于扫描元组,并存放在slot中。在src/backend/executor/nodeSeqscan.c文件中的SeqNext函数的之后会使用table_scan_getnextslot,用于从表中获取下一个元组。

/* Return next tuple from `scan`, store in slot. */
static inline bool table_scan_getnextslot(TableScanDesc sscan, ScanDirection direction, TupleTableSlot *slot) {
	slot->tts_tableOid = RelationGetRelid(sscan->rs_rd);
	return sscan->rs_rd->rd_tableam->scan_getnextslot(sscan, direction, slot);
}

scan_end

table_endscan函数用于结束表的扫描。在src/backend/executor/nodeSeqscan.c文件中的ExecEndSeqScan函数中最后执行TableScanDesc的清理工作。

/* End relation scan. */
static inline void table_endscan(TableScanDesc scan){
	scan->rs_rd->rd_tableam->scan_end(scan);
}

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

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

相关文章

初识Docker:(5)Docker自定义镜像

初识Docker&#xff1a;&#xff08;5&#xff09;Docker自定义镜像镜像结构Dockerfile语法什么是Dockerfile构建Java项目案例1&#xff1a;基于ubuntu镜像构建一个新镜像&#xff0c;运行一个java项目案例2&#xff1a;基于java:8-alpine镜像&#xff0c;将一个java项目构建为…

Java+JSP机房课表管理系统(含源码+论文+答辩PPT等)

项目功能简介: 该项目采用技术CSSJavaScriptMySQLServlet、MySQL数据库、项目含有源码、配套开发软件、软件安装教程、项目发布教程等 项目功能介绍&#xff1a; 系统管理&#xff1a;包含用户的注册&#xff0c;管理&#xff0c;信息修改 课程管理&#xff1a;包含课程录入、维…

IT大侦“碳”:VxRail的可持续法宝

环境Environmental      社会责任Social Responsibility      企业治理Corporate Governance      随着碳达峰、碳中和的逐步推进,越来越多的“大厂”或各行业的明星企业都开始重视自己的ESG报告,已然成为了商界新风尚。      可持续发展战略也与前沿技术密切相…

matlab神经网络求解最优化,matlab神经网络训练数据

1、神经网络的准确率是怎么计算的&#xff1f; 其实神经网络的准确率的标准是自己定义的。 我把你的例子赋予某种意义讲解&#xff1a; 1&#xff0c;期望输出[1 0 0 1]&#xff0c;每个元素代表一个属性是否存在。像着4个元素分别表示&#xff1a;是否肺炎&#xff0c;是否肝…

哈希知识点

目录对比map/set1. unordered系列关联式容器1.1 unordered_map2. 底层结构2.1 哈希概念2.2 哈希冲突2.3 哈希函数2.4 哈希冲突解决2.4.1 闭散列线性探测和二次探测扩容&#xff08;负载因子&#xff09;闭散列实现的hash2.4.2 开散列概念开散列思考实现模拟实现模板参数列表的改…

Java项目:springboot农业物资管理系统

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 农业物资管理系统&#xff0c;管理员可以对角色进行配置&#xff0c;分配用户角色&#xff1b; 主要功能包含&#xff1a;登录、注册、修改密码…

并查集解决重复员工问题

简介 工作一年多了&#xff0c;天天CRUD&#xff0c;终于以前学习的算法排上用场了。 背景 我们的系统在用户注册时没有校验身份id&#xff08;身份证&#xff09;和电话号码的唯一&#xff0c;可能使用相同的身份id或者电话号码创建多个账号&#xff0c;导致有些人开多个账…

面试者推荐 |【Redis面试专题】「常见问答系列」透析Redis常见技术相关的问题1~10题(进阶)

&#x1f4da; 前提回顾 首先如果没有阅读【面试者推荐 |【Redis面试专题】「常见问答系列」透析Redis常见技术相关的问题1~10题&#xff08;基础&#xff09; 】&#xff0c;简易先去看看基础10题&#xff0c;因为循序渐进才是正道&#xff0c;哈哈。 &#x1f4da; 1. Redis…

WebRTC源码之RTCPReceiver源码分析

WebRTC源码之RTCPReceiver源码分析 WebRTC源码之RTCPReceiver源码分析WebRTC源码之RTCPReceiver源码分析前言一、 RTCP接受数据的流程的堆栈信息的1、网络io 线程读取数据2、 线程切换的代码3、 线程切换 gcc二、 RTCPReceiver::IncomingPacket方法读取RTCP数据的格式1、 Parse…

【PyTorch深度学习项目实战100例】—— 基于DPCNN实现电商情感分析任务 | 第79例

前言 大家好,我是阿光。 本专栏整理了《PyTorch深度学习项目实战100例》,内包含了各种不同的深度学习项目,包含项目原理以及源码,每一个项目实例都附带有完整的代码+数据集。 正在更新中~ ✨ 🚨 我的项目环境: 平台:Windows10语言环境:python3.7编译器:PyCharmPy…

随机种子 3407 is all you need

文 | 天于刀刀你最常用的随机种子是哪个&#xff1f;在刀刀的团队里&#xff0c;关于随机种子的设置主要分化为两派~玄学派&#xff0c;可能设置为自己的纪念日&#xff0c;又或者是星座预测中的本月幸运数字&#xff1b;以及&#xff0c;自然派&#xff0c;随机种子是啥其实无…

Java项目:springboot健身房管理系统

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 本项目为后台管理系统&#xff1b; 主要功能如下&#xff1a; 管理员登录模块 会员管理模块 教练管理模块 课程管理模块 器材管理模块 物品遗失…

一些常见的移动端适配方案,你了解吗?

前言 移动端设备的尺寸很多&#xff0c;而 UI 设计稿一般只会基于一个尺寸&#xff08;一般是 375px 或 750px &#xff09;进行设计。 目前移动端适配方案有多种&#xff0c;本文将介绍一些具有代表性的适配方案。 媒体查询 media CSS3 中的媒体查询属性 media 分别为不同…

量子计算(十七):量子计算机硬件

文章目录 量子计算机硬件 一、量子芯片支持系统 二、量子计算机控制系统 量子计算机硬件 量子计算机的核心——量子芯片&#xff0c;具有多种不同的呈现形式。绝大多数量子芯片&#xff0c;名副其实地&#xff0c;是一块芯片&#xff0c;由集成在基片表面的电路结构构建出包…

关于 Camera 开始 Tuning 时的一些注意事项

1、问题背景&#xff1a; 最近有调试一个体感游戏机上带 Camera 的项目&#xff0c;原定搭配 ov13855 这颗 sensor, 但由于各种各样的问题&#xff0c;导致做了很多无用功&#xff0c;且各种延期。 本文主要总结下此次项目遇到的问题&#xff0c;及产品开始 tuning 时的一些注意…

【折腾服务器 4】ESXi 中 Ubuntu 安装 NPS 客户端 ( NPC )

Catch Up 书接上回&#xff0c;上一章中&#xff0c;群晖已经能定期给 Windows 物理机服务器做备份了&#xff0c;但是依然无法从外网访问服务器上的内容&#xff0c;本篇讲述如何在 Ubuntu 中安装 NPS 客户端&#xff0c;也就是所谓的 NPC ( Client )。 Chapter 1 准备一个 …

C#语言实例源码系列-实现FTP下载文件

专栏分享点击跳转>Unity3D特效百例点击跳转>案例项目实战源码点击跳转>游戏脚本-辅助自动化点击跳转>Android控件全解手册 &#x1f449;关于作者 众所周知&#xff0c;人生是一个漫长的流程&#xff0c;不断克服困难&#xff0c;不断反思前进的过程。在这个过程中…

SpringSecurity(十)【CSRF 漏洞保护】

十、CSRF 漏洞保护 简介 CSRF&#xff08;Cross-Site Request Forgery 跨站请求伪造&#xff09;&#xff0c;也可称为一键式攻击&#xff08;one-click-attack&#xff09;通常缩写为 CSRF 或者 XSRF。CSRF 攻击是一种挟持用户在当前已登录的浏览器上&#xff0c;发送恶意请求…

Python绘制地磁场

文章目录简介磁场绘制简介 为国际参考磁场对Python的封装&#xff0c;可通过经纬高度以及时间来计算地磁场强度&#xff0c;使用方法简单粗暴&#xff0c;如下 import pyIGRF pyIGRF.igrf_value(lat, lon, alt, date)参数含义为 lat 纬度lon 经度alt 海拔date 日期&#xff…

vuejs中组件的两种不同的编写风格-选项式API及组合式API

前言随着vue3的逐渐稳定,以及周边生态的完善,现在vue3已经成为默认的使用方式了的所以,对于一个前端开发者,Vue2与Vue3都得要会,在vue3中新增很多东西,比如:Fragment,Teleport,Suspense,也去掉了vue2中一些特性,比如:移除keyCode支持作为v-on的修饰符等在编程风格上也有一些区别…