PgSQL技术内幕-Bitmap Index Scan

PgSQL技术内幕-Bitmap Index Scan

1、简介

Bitmap索引扫描是对索引扫描的一个优化,通过建立位图的方式将原来的随机堆表访问转换成顺序堆表访问。主要分为两点:1)管理每个Bitmap的hash slot没用完时,每个Bitmap代表每个heap页中满足条件元组的ItemIDs,通过Bitmap扫描heap页时需要将所有Bitmap按照页号进行排序,然后依次获取heap页中记录,依次完成顺序回表。2)当hash slot用完时,就需要将heap页的bitmap范围扩大,转换成一个chunk的bitmap,也就是Bitmap中一位代表页内具有满足条件元组的页。此时,整个Bitmaps有chunk的bitmap也有页的bitmap,该chunk的页号为chunk内最小页号,所以Bitmaps排序后,整体上也是有序的。如此完成顺序扫描heap页,只不过对于Chunk的bitmap中一位代表的heap 页需要再次进行条件检测,将满足条件的tuple输出。

2、Bitmap Index Scan中的Bitmap是什么

Bitmap index scan先利用索引获取满足条件的Tid,将其保存到TIDBitmap中。由TIDBitmap管理满足条件的heap tuple的Bitmap。TIDBitmap结构主要成员如下图所示:

c08016319958a4b8485e1f80ad585259.png

各个成员变量的说明:

1)每一页的bitmap由PagetableEntry结构来管理,里面成员主要有blockno:页号,用做hash表的key。最初仅使用entry1,entry1满了,才会使用hash表。这样btgetbitmap扫描完成所有存在的TID,就完成了按照页聚合。

2)pagetable哈希表,初始时(tbm_create调用时指定)仅创建128个hash桶。若一个page对应一个PagetableEntry,当有大量page需要构建bitmap时,就不够用了。所以Hash桶用完则转换chunk进行lossy,从而腾出空闲槽。等hash桶都变成chunk时,就需要扩展了,每次扩展2倍大小(2*128)。

3)nentries表示hash表中已使用桶的个数

4)maxentries为hash表hash桶的最大个数限制。该成员主要作用:控制何时进行lossy,也就是nentries > maxentries时,需要tbm_lossify。大小由work_mem控制,至少16个。当然,如果最终扩展的超过work_mem时,桶仍旧都是chunk,则更新maxentries扩展2倍大小。

5)entriy1表示最开始使用的entry,不用申请到hash表

6)spages和schunks则是从hash桶弄过来排过序的entry。在BitmapHeapScan阶段使用。当然,分别存储Page和lossy的chunk。这样就可以顺序访问了。

另外TIDBitmap中的几个成员有:

1)TBMStatus status:

typedef enum
{TBM_EMPTY, /* no hashtable, nentries == 0 */TBM_ONE_PAGE, /* entry1 contains the single entry */TBM_HASH /* pagetable is valid, entry1 is not */
} TBMStatus;

为什么会有TBM_ONE_PAGE和TBM_HASH呢?因为如果TIDBitmap只存储一个PagetableEntry,不需要耗费实际构建动态hash表,查找时也不需要通过hash查找,只需要使用entry1即可。

3、Bitmap Index Scan阶段

MultiExecBitmapIndexScan函数实现了Exec逻辑,主要通过调用index_getbitmap函数,获取bitmap,然后将bitmap返回给上一层算子。我们这里以btree索引为例,所以index_getbitmap指向btgetbitmap索引扫描函数:

7f34eddaec40c760726f99bef1716bba.png

btgetbitmap函数的逻辑:当然时先创建TIDBitmap,然后调用_bt_first/_bt_next逐条获取满足条件的item,接着通过tbm_add_tuples将其添加到TIDBitmap中,最终构建一个完整的bitmap,核心函数为_bt_first/_bt_next/tbm_add_tuples:

0291ffd509c9d55f8e8ef068b99d3388.png

1)_bt_first函数时索引扫描的开始。首先调用_bt_preprocess_keys预处理扫描key,所扫描key条件无法满足,则设置BTScanOpaque->qual_ok为false,提前结束扫描。若没有找到有用的边界keys,需要调用_bt_endpoint从第一页开始,否则调用_bt_search从btree的root节点_bt_getroot开始扫描,直到找到符合扫描key和快照的第一个叶子节点。之后使用二分查找_bt_binsrch找到符合扫描key的页内item偏移,最好将找到的页面载入buffer并返回tuple。

2)_bt_next函数从当前页获取下一条tuple,若当前页没有tuple,则调用_bt_steppage拿到下一页页号,之后调用_bt_readnextpage读取文件块中的内容,然后_bt_next获取吓一跳tuple,重复以上过程,直至扫描结束。

3)tbm_create创建TIDBitmap:

eeeb1e996b6e4766faf472c5299c6010.png

4)tbm_add_tuples函数添加CTID,构建TIDBitmap

837d2f9ed80b6ef265a63c4b76b06c99.png

tbm_add_tuples要干的事如上图所示:

(1)btgetbitmap调用tbm_add_tuples每次仅添加一个TID,从TID中解析出对应heap tuple的页号blk及页内偏移off

(2)判断blk是否是lossy:页号定位到所属chunk;然后据该chunk页号从hash表中查找;hash表中找到,再看下页号所属的bitmap位是否1,即是否lossy;bitmap为1,则返回true:

a31c88e749272f9f4756d306abfff515.png

blk非lossy,则调用tbm_get_pageentry从hash表中找一个PagetableEntry(不存在则会创建)。但是若此时只有一个PagetableEntry(TBM_ONE_PAGE状态)则直接返回entry1,不需要从hash查找:

b06e45eb9630b5b883058630889187e2.png

blk是lossy:已经位于chunk中的一位了,不必再向hash表添加了,因为btree下仅一个TID,所以退出循环

(3)计算bitmap的位于哪个字节wordnum及哪一位bitnum,标记到PagetableEntry的bitmap中words,并设置recheck为false

(4)tbm_get_pageentry创建了一个新PagetableEntry,发现npages超过tbm->maxentries只,则会调用tbm_lossify函数,将TIDBitmap中部分PagetableEntry转成成lossy chunk,同时按照exact page的减少和lossy page的增加,相应修改npages和nchunks

tbm_lossify函数

8a7ec42e8fc7794fbf990a791edf2ab9.png

那么hash表何时扩展呢?只要向hash表插入PagetableEntry,就有可能涉及到扩展,扩展后maxentries并不是立即更新;pagetable_insert调用结束后,若插入则需要更新nentries

de1d2939506a64ff34fdd3db9407c222.png

当然,还会有Bitmap And和Bitmap Or的情况。BitmapAnd节点对两个Bitmap进行与操作,生成交集位图;BitmapOr节点对两个Bitmap进行或操作,生成并集位图。

至此,bitmap index scan阶段完成bitmap的构建,下一步就是根据TID bitmap来扫描heap,返回符合条件的tuple,即Bitmap Heap Scan。

4、Bitmap Heap Scan阶段

Bitmap Heap Scan使用Bitmap Index Scan阶段生成的bitmap来查找相关数据。位图的每个页可以是精确的(直接指向heap页的tuple),也可以是有损的(指向包含至少一行与查询匹配的页)。算子由ExecBitmapHeapScan函数执行,主要实现函数为BitmapHeapNext:

c128cb415214e9767e8dd248449d69ac.png

BitmapHeapNext的核心逻辑如下:

4b2da4979f78377cebef69e0aecd8b34.png

1)从下层节点拿到TIDBitmap结果tbm

2)tbm_generic_begin_iterate->tbm_begin_iterate基于tbm构建一个iterator:从hash表中取出PagetableEntry,根据它是exact page还是lossy page,分别放到spages[]和schunks[]数组;然后根据页号进行排序

cfc344a30120f2ee5be3ba2f826b183d.png

3)先调用tbm_iterate从spages[]和schunks[]数组拿一个较小页号的页,然后通过table_scan_bitmap_next_block->heapam_scan_bitmap_next_block读取一个page到ScanDesc的rs_buffer里。

cd18133056957e18cefc68fbcb0a1bf6.png

4)调用table_scan_bitmap_next_tuple->heapam_scan_bitmap_next_tuple根据TBMIterateResult里的偏移,再内存buffer里获取相应的tuple。当这一页扫描完,则重置node->tbmres = tbmres = NULL,重新获取下一个PagetableEntry的bitmap继续循环。

5)如果是lossy,则还需要继续过滤

5、总结

Bitmap索引扫描分为两个阶段,第一阶段通过索引进行扫描,将满足条件的元组TID构建到bitmap中,一般情况一个页一个bitmap;第二阶段将bitmap按照页号进行排序,按次序从页的bitmap中取出heap tuple的TID,从而达到索引顺序扫描heap的目的。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

nn.KLDivLoss,nn.CrossEntropyLoss,nn.MSELoss,Focal_Loss

KL loss:https://blog.csdn.net/qq_50001789/article/details/128974654 https://pytorch.org/docs/stable/nn.html 1. nn.L1Loss 1.1 公式 L1Loss: 计算预测 x和 目标y之间的平均绝对值误差MAE, 即L1损失: l o s s 1 n ∑ i 1 , . . . n ∣ x i…

【Flink】系统架构

DataStream API 将你的应用构建为一个 job graph,并附加到 StreamExecutionEnvironment 。当调用 env.execute() 时此 graph 就被打包并发送到 JobManager 上,后者对作业并行处理并将其子任务分发给 Task Manager 来执行。每个作业的并行子任务将在 task…

矩阵运算_矩阵的协方差矩阵/两个矩阵的协方差矩阵_求解详细步骤示例

1. 协方差矩阵定义 在统计学中,方差是用来度量单个随机变量的离散程度,而协方差则一般用来刻画两个随机变量的相似程度。 参考: 带你了解什么是Covariance Matrix协方差矩阵 - 知乎 2. 协方差矩阵计算过程 将输入数据A进行中心化处理得到A…

【开源】基于Vue.js的创意工坊双创管理系统

项目编号: S 049 ,文末获取源码。 \color{red}{项目编号:S049,文末获取源码。} 项目编号:S049,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 管理员端2.2 Web 端2.3 移动端 三、…

你知道什么是SaaS吗?

你知道什么是SaaS吗? 云服务架构的三个概念 PaaS 英文就是 Platform-as-a-Service(平台即服务)PaaS,某些时候也叫做中间件。就是把客户采用提供的开发语言和工具(例如Java,python, .Net等)开…

【每日一题】三个无重叠子数组的最大和

文章目录 Tag题目来源题目解读解题思路方法一:滑动窗口 写在最后 Tag 【滑动窗口】【数组】【2023-11-19】 题目来源 689. 三个无重叠子数组的最大和 题目解读 解题思路 方法一:滑动窗口 单个子数组的最大和 我们先来考虑一个长度为 k 的子数组的最…

Redux-状态管理组件

一、简介 react中的状态只属于某个组件。而Redux是一个全局管理js状态的架构,让组件通信更加容易。 之前是状态在所有组件间传递,而redux通过store来实现这个功能。 Redux特性: 1.Single source Of truth,通过store唯一维护状态…

电子学会C/C++编程等级考试2022年03月(一级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:双精度浮点数的输入输出 输入一个双精度浮点数,保留8位小数,输出这个浮点数。 时间限制:1000 内存限制:65536输入 只有一行,一个双精度浮点数。输出 一行,保留8位小数的浮点数。样例输入 3.1415926535798932样例输出 3.1…

【Android】使用Retrofit2发送异步网络请求的简单案例

添加网络权限到AndroidManifest.xml清单文件 为了让你的Android应用程序能够使用互联网进行通信&#xff0c;你需要在AndroidManifest.xml文件中添加网络权限声明。<uses-permission android:name"android.permission.INTERNET"/> 这个权限应该添加到 Android…

76基于matlab的免疫算法求解配送中心选址问题,根据配送地址确定最佳配送中心地址位置。

基于matlab的免疫算法求解配送中心选址问题&#xff0c;根据配送地址确定最佳配送中心地址位置。数据可更换自己的&#xff0c;程序已调通&#xff0c;可直接运行。 76matlab免疫算法配送中心选址 (xiaohongshu.com)

我又开始贩卖焦虑了,机器视觉兄弟们,打工这生意盘不活了?让人逃离北上广深,是毒鸡汤吗?

我想大多数人和我想的一样&#xff0c;不要质疑自己的出身&#xff0c;也不必用一生去改变出身而获得融入感&#xff0c;思想富足这是我们留给自己一生最珍贵的礼物。也许一线城市容不下肉身&#xff0c;二三线城市容不下灵魂。那我回到生我养我的十八线小县城&#xff0c;这不…

人力资源小程序

人力资源管理对于企业的运营至关重要&#xff0c;而如今随着科技的发展&#xff0c;制作一个人力资源小程序已经变得非常简单和便捷。在本文中&#xff0c;我们将为您介绍如何通过乔拓云网制作一个人力资源小程序&#xff0c;只需五个简单的步骤。 第一步&#xff1a;注册登录乔…