当前位置: 首页 > news >正文

PgSQL HashAgg算法 | 第2期 | 版本12的spill溢出磁盘解秘

PgSQL HashAgg算法 | 第2期 | 版本12的spill溢出磁盘解秘

HashAgg需要在内存中构建Hash表,以此来构建聚合分组;但是当数据量大到内存放不下时,就需要spill溢出到磁盘;构建好当前hash表并输出分组值后,再将磁盘上的spill文件中数据加载重新构建hash表并构建聚合分组。PgSQL在演进过程中,有两种spill磁盘方式,本期介绍如何spill并根据磁盘临时文件构建聚合分组。

21574093885497860de5ac314c2cddbd.png

Spill的管理方式如上图所示,源头信息都存放在AggState中,分布为HashTapeInfo* hash_tapeinfo和HashAggSpill* hash_spills。

1)num_hashes为分组聚合中Hash Keys分组集个数,比如group by grouping sets((id1),(id2),(id3))中,就由3个分组集,即num_hashes值为3

2)hash_tapeinfo为该AGG使用的临时文件的tapes信息,其中ntapes为tape总个数,会有回收和复用,空闲tape由freetapes管理

3)LogicalTapeSet包含一个BufFile* pfile,管理着多个文件,当一个临时文件写满1GB后,会写如下一个文件

4)LogicalTapeSet还管理LogicalTape* tapes数组

5)再返回到AggState结构中,HashAggSpill* hash_spills数组大小为num_hashes个数,也就是每个分组集对应一个hash_spills[]

6)HashAggSpill由一个partitions数组,存放着分配的tapes[]下标号。Tapes写到磁盘时,buffer的尾部会有一个结构TapeBlockTrailer,保存前后block号,这样形成一个链表,读时,通过该链表将同一个tabpes[]的数据读取出来

9f6952d70912205dd4898d0bb5ca3cfd.png

因为写入的时候,根据hash值确定使用哪个tapes[],所以一个tapes[]中存放的近似一个分组的所有值(由于会有hash冲突场景,也包括不是一个分组的值)

简单了解数据读写管理后,我们接着看下HashAgg的spill流程

bd1b9cea7e3fb924eea3e7bade68133d.png

agg_fill_hashtable构建hash表,然后通过agg_retrieve_hash_table从hash表中获取分组聚合值,若有spill,则hash表取完后,再从磁盘临时文件加载重新构建下一批分组聚合的hash表。

1)agg_fill_hash_table调用lookup_hash_entries构建所有set的hash表;调用hashagg_finish_initial_spills处理所有临时文件的元数据

2)lookup_hash_entries对所有Hash Key组进行构建hash表,若一个Hash key组的hash表构建过程中发生spill磁盘,则后面其他Hash Key组的hash表全部会spill磁盘

3)首先每个Hash Key组通过调用hashagg_spill_init初始化各自的HashAggSpill,管理各自的partitions[]数组等

4)hashagg_spill_tuple将tuple写到Hash Key组对应的tape链表,当然是统一写到一个文件,当文件满1GB则写入下一个文件。写下去的tuple包括所有需要的列,不仅仅是当前set需要的列

5)所有set全部spill完后,调用hashagg_spill_finish,遍历各自的partitions[]数组,每个tape形成一个HashAggBatch,记录有setno和tapenum,最终将所有HashAggBatch构建成一个链表hash_batches

6)agg_retrieve_hash_table先调用agg_retrieve_hash_table_in_memory从hash表取出分组值,取完后再调用agg_refill_hash_table从磁盘文件中读取记录重新构建hash表,并计算分组聚合值

7)agg_refill_hash_table可知从hash_batches链表取出一个HashAggBatch,得到setno和tapenum,从而从临时文件中读取该tape的所有值构建到hash表中。本次是一个tape的构建,弄好后,需要从hash表输出,之后再次进入该函数,重新从hash_batches链表取一个HashAggBatch继续下一个tape的读取

8)这里需要注意,有可能会再次spill,并且可能写到之前同一个临时文件中,并追加到同一个链表hash_batches。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • linux之ELK
  • [Hdp] lc552. 学生出勤记录 II(dp+递推+状态定义+状态转移+向前转移+好题)
  • Clichouse数据导出导入(数据迁移)
  • 重头开始嵌入式第二十三天(进程2)
  • Unity | 性能优化
  • 【分享】格力手机色界G0245D 刷REC、root、 救砖、第三方rom教程和资源
  • 论文辅导 | 基于改进灰色预测模型的港口物流需求预测研究
  • opencv图像基本操作
  • [MRCTF2020]套娃1
  • 实验五之用Processing绘画
  • 洛谷p4018题解
  • GAMES104:07游戏中渲染管线、后处理和其他的一切-学习笔记
  • 【运维】从一个git库迁移到另一个库
  • 【设计模式】工厂模式和抽象工厂模式
  • 2020 位示图
  • 分享的文章《人生如棋》
  • [nginx文档翻译系列] 控制nginx
  • [原]深入对比数据科学工具箱:Python和R 非结构化数据的结构化
  • 【347天】每日项目总结系列085(2018.01.18)
  • 30天自制操作系统-2
  • Cookie 在前端中的实践
  • IndexedDB
  • JAVA之继承和多态
  • Mysql优化
  • pdf文件如何在线转换为jpg图片
  • QQ浏览器x5内核的兼容性问题
  • SegmentFault 技术周刊 Vol.27 - Git 学习宝典:程序员走江湖必备
  • yii2中session跨域名的问题
  • 程序员该如何有效的找工作?
  • 大主子表关联的性能优化方法
  • 好的网址,关于.net 4.0 ,vs 2010
  • 视频flv转mp4最快的几种方法(就是不用格式工厂)
  • 数据结构java版之冒泡排序及优化
  • 算法之不定期更新(一)(2018-04-12)
  • 为什么要用IPython/Jupyter?
  • 学习ES6 变量的解构赋值
  • 学习Vue.js的五个小例子
  • 学习使用ExpressJS 4.0中的新Router
  • Salesforce和SAP Netweaver里数据库表的元数据设计
  • 分布式关系型数据库服务 DRDS 支持显示的 Prepare 及逻辑库锁功能等多项能力 ...
  • ​无人机石油管道巡检方案新亮点:灵活准确又高效
  • # .NET Framework中使用命名管道进行进程间通信
  • (13)Latex:基于ΤΕΧ的自动排版系统——写论文必备
  • (java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
  • (二)换源+apt-get基础配置+搜狗拼音
  • (机器学习-深度学习快速入门)第三章机器学习-第二节:机器学习模型之线性回归
  • (考研湖科大教书匠计算机网络)第一章概述-第五节1:计算机网络体系结构之分层思想和举例
  • (转载)Google Chrome调试JS
  • .a文件和.so文件
  • .NET COER+CONSUL微服务项目在CENTOS环境下的部署实践
  • .Net Core与存储过程(一)
  • .NET/ASP.NETMVC 深入剖析 Model元数据、HtmlHelper、自定义模板、模板的装饰者模式(二)...
  • .NET/C#⾯试题汇总系列:⾯向对象
  • .Net7 环境安装配置
  • ?php echo ?,?php echo Hello world!;?