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.rhkb.cn/news/199434.html

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

相关文章

【蓝桥杯选拔赛真题23】C++计算24 第十二届蓝桥杯青少年创意编程大赛C++编程选拔赛真题解析

C/C++计算24 第十二届蓝桥杯青少年创意编程大赛C++选拔赛真题 一、题目要求 1、编程实现 “计算 24”是一个流传已久的数字游戏,小蓝最近对此痴迷不已 游戏规则是:从 1~10 之间的自然数任意拿出 4 个数(4 个数各不相同,顺序随机),进行加、减、乘三种运算(使用某种运算…

什么是BT种子!磁力链接又是如何工作的?

目录 一.什么是BT?1.BT简介:1.1.BT是目前最热门的下载方式之一1.2.BT服务器是通过一种传销的方式来实现文件共享的 2.小知识:2.1.你知道吗BT下载和常规下载到底有哪些不同2.2.BT下载的灵魂:种子2.3.当下载结束后,如果未…

matlab 坡度滤波算法地面分割

目录 一、算法原理1、实现流程2、参考文献二、代码实现三、结果展示四、测试数据一、算法原理 1、实现流程 1、格网示意图 2、计算格网行列数 公式中的特殊符号为向上取整,

初识分布式键值对存储etcd

欢迎大家到我的博客浏览。胤凯 (oyto.github.io)大家好,今天我带大家来学习一下 etcd。 一、什么是 etcd etcd 是一个开源的分布式键值存储系统,主要用于构建分布式系统中那点服务发现、配置管理、分布式锁等场景。它采用 Raft 一致性算法来确保所有节…

面试题-6

1.精灵图和base64的区别是什么? 精灵图:把多张小图整合到一张大图上,利用定位的一些属性把小图显示在页面上,当访问页面可以减少请求,提高加载速度 base64:传输8bit字节代码的编码方式,把原本二进制形式转为64个字符的单位,最后组成字符串 …

物联网赋能:WIFI HaLow在无线连接中的优势

在探讨无线网络连接时,我们不难发现,WIFI已经成为我们日常生活中不可或缺的一部分,承载了半数以上的互联网流量,并在家庭、学校、娱乐场所等各种场合广泛应用。然而,尽管WIFI4、WIFI5和WIFI6等协议无处不在&#xff0c…

记一次线上bug排查-----SpringCloud Gateway组件 请求头accept-encoding导致响应结果乱码

基于公司的业务需求,在SpringCloud Gateway组件的基础上,写了一个转发服务,测试开发阶段运行正常,并实现初步使用。但三个月后,PostMan请求接口,返回异常,经排查,从日志中获取到转发…

嵌入式QTGit面试题

自己在秋招过程中遇到的QT和嵌入式和Git相关的面试题,因为比较少就一起放了 QT connect第5个参数是什么? Qt::AutoConnection: 默认值,使用这个值则连接类型会在信号发送时决定。 如果接收者和发送者在同一个线程,则…

SVG圆形 <circle>的示例代码

本专栏是汇集了一些HTML常常被遗忘的知识,这里算是温故而知新,往往这些零碎的知识点,在你开发中能起到炸惊效果。我们每个人都没有过目不忘,过久不忘的本事,就让这一点点知识慢慢渗透你的脑海。 本专栏的风格是力求简洁…

RabbitMQ 部署及配置详解(集群部署)

单机部署请移步: RabbitMQ 部署及配置详解 (单机) RabbitMQ 集群是一个或 多个节点,每个节点共享用户、虚拟主机、 队列、交换、绑定、运行时参数和其他分布式状态。 一、RabbitMQ 集群可以通过多种方式形成: 通过在配置文件中列出群集节点以…

pnpm : 无法加载文件 E:\Soft\PromSoft\nodejs\node_global\pnpm.ps1,

pnpm : 无法加载文件 E:\Soft\PromSoft\nodejs\node_global\pnpm.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/go.microsoft.com/fwlink/?LinkID135170 中 的 about_Execution_Policies。 所在位置 行:1 字符: 1pnpm -v~~~~ CategoryI…

linux高级篇基础理论五(用户安全,口令设置,JR暴力破解用户密码,NMAP端口扫描)

♥️作者:小刘在C站 ♥️个人主页: 小刘主页 ♥️不能因为人生的道路坎坷,就使自己的身躯变得弯曲;不能因为生活的历程漫长,就使求索的 脚步迟缓。 ♥️学习两年总结出的运维经验,以及思科模拟器全套网络实验教程。专栏:云计算技…

使用Python的turtle模块绘制玫瑰花图案(含详细Python代码与注释)

1.1引言 turtle模块是Python的标准库之一,它提供了一个绘图板,让我们可以在屏幕上绘制各种图形。通过使用turtle,我们可以创建花朵、叶子、复杂的图案等等。本博客将介绍如何使用turtle模块实现绘制图形的过程,并展示最终结果。 …

【Linux】【开发】使用sed命令遇到的乱码问题

🐚作者简介:花神庙码农(专注于Linux、WLAN、TCP/IP、Python等技术方向)🐳博客主页:花神庙码农 ,地址:https://blog.csdn.net/qxhgd🌐系列专栏:Linux技术&…

机器学习笔记 - Ocr识别中的CTC算法原理概述

一、文字识别 在文本检测步骤中,分割出了文本区域。现在需要识别这些片段中存在哪些文本。 机器学习笔记 - Ocr识别中的文本检测EAST网络概述-CSDN博客文章浏览阅读300次。在 EAST 网络的这个分支中,它合并了 VGG16 网络不同层的特征输出。现在,该层之后的特征大小将等于 p…

Ubuntu18.04运行gazebo的launch文件[model-4] process has died报错

启动gazebo仿真环境报错[model-4] process has died [model-4] process has died [pid 2059, exit code 1, cmd /opt/ros/melodic/lib/gazebo_ros/spawn_model -urdf -model mycar -param robot_description __name:model __log:/root/.ros/log/8842dc14-877c-11ee-a9d9-0242a…

猫12分类:使用多线程爬取图片的Python程序

本文目标 对于猫12目标检测部分的数据集,采用网络爬虫来制作数据集。 在网络爬虫中,经常需要下载大量的图片。为了提高下载效率,可以使用多线程来并发地下载图片。本文将介绍如何使用Python编写一个多线程爬虫程序,用于爬取图片…

Wireshark抓包:理解TCP三次握手和四次挥手过程

TCP是一种面向连接、端到端可靠的协议,它被设计用于在互联网上传输数据和确保成功传递数据和消息。本节来介绍一下TCP中的三次握手和四次挥手。 文章目录 1 TCP头部格式2 wireshark抓包分析2.1 SEQ和ACK2.2 三次握手2.3 四次挥手 3 程序 1 TCP头部格式 TCP头部占据…

Pandas+Matplotlib 数据分析

利用可视化探索图表 一、数据可视化与探索图 数据可视化是指用图形或表格的方式来呈现数据。图表能够清楚地呈现数据性质, 以及数据间或属性间的关系,可以轻易地让人看图释义。用户通过探索图(Exploratory Graph)可以了解数据的…

srs webrtc推拉流环境搭建(公网)

本地环境搭建 官方代码https://github.com/ossrs/srs 拉取代码: git clone https://github.com/ossrs/srs.gitcd ./configure make ./objs/srs -c conf/https.rtc.confsrs在公网上,由于srs是lite-ice端,导致他不会主动到srs获取自己的公网i…