热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

PG向量化引擎2

PG向量化引

PG 向量化引擎--2

向量化引擎是OLAP数据库提升性能的有效技术。翻到PostgreSQL邮件列表有对向量化引擎的讨论。这里继续进行整理,以作分析。

关于设计中的几个问题

1、在vtype中使用原生数组而不是Datum数组会更有效吗?我认为针对float4int32类型的操作,它将允许编译器产生更加有效的代码

是的,我也在考虑扫描列存时,将列batch加载到连续的内存区域中。对于Int32,此区域大小时4*BATCHSIZE,而对于Int16,大小时2*BATCHSIZE。所以使用原生数据可以只做一个memcpy来填充vtypebatch

2、为什么VectorTupleSlot中包含元组的数据(batch)而不是向量(vtype的数组)?

首先,VectorTupleSlottts_values域存储vtype的数组,这样做减少了代码的更改量,摈弃可以重用像ExecProject类似的函数。当然,我们也可以使用单独的字段来存储vtypes

其次,VectorTupleSlot还包含堆元组数据。这属于堆元组的变形。事实上,一个batch中包含的元组可能跨多个页。因此我们需要pin住相关页的数组,而不仅仅是一个页

3、为什么必须实现子集的plan_tree_mutator而不是使用expression_tree_mutator?

我也想要替换Plan节点,例如Agg->CustomScan(使用VectorAgg实现)expression_tree_mutator不能够用于变异plan node,如Agg,对吗?

4、据我了解,您现在总是尝试用自己定义的向量化scan来替代SeqScan。但只有当此扫描或聚合执行了quals才有意义。其他情况下,batch+unbatch只会增加额外的开销,不是吗?

可能heap格式和select i from t没有qualprojectionaggregation的查询才会有额外的开销。但是对于列存,VectorScan可以直接读batch,没有额外的batch代价。列存是OLAP查询更好的选择。我们是否可以得出结论,对于OLAP查询使用向量化引擎,对于OLTP查询使用行引擎会更好。

5、对于不能向量化的查询捕获并抛出异常不是处理此类情况最安全和最有效的方法。在plan_tree_mutator中返回错误代码,并将此错误传播到上层可能会更好吗?

是的,至于效率,另一种方法是仅对某些plan节点进行向量化,而其他节点不向量化,通过在他们之间添加batch/unbatch节点来实现(这是你说的“在上层传播此错误”?)。正如您所提到的,这可能会带来额外的开销,还有其他好的方法吗?您说的最不安全是什么意思?PG catch接收ERROR,反馈给原始非向量化plan

--hackers中对catching和忽略exception进行了多次讨论,不幸的是PGPG_TRY/PG_CATCH机制不是高级语言C++java等机制的变种。它不会执行堆栈unwind。如果在抛出错误之前获取了一些资源(fileslocksmemory等),那么这些资源不会回收。仅回滚事务才能释放所有资源。实际上它发生在正常错误处理情况下。但如果捕获并忽略异常,视图继续执行,那么可能会导致更多问题。

可能在您情况下,这个不是问题,因为您确定错误发生在哪里,他是由plan_tree_mutator抛出的,并且看起来这个函数没有获得任何资源。但是在任何情况下setjmp开销都远高于对返回码的显式检查。因此,检查返回码实际上不会增加一些明显的开销,除了通过添加额外的检查使得代码复杂化。但是可以通过宏例如MUTATE来隐藏这些复杂度。

6、你测试过不同batch大小吗?我在VOPS中做了类似测试,发现大于128的大小并没有带来显著的性能提升。你当前使用batch大小是1024,它明显大于一页上元组数量。

好的,将对此进行一些实验

7、如何将向量化扫描和并行结合起来(9.6已支持)

目前还没实现。但这个想法与非并行的想法相同。复制当前并行扫描并实现向量化Gather,保持接口都是VectorTupleTableSlot。我们基本思路是复用当前PG执行逻辑大部分代码,然后进行向量化,并逐步进行性能调优。

--并行扫描时在并行worker之间分散页。为填充VectorTupleSlot,可能需要不止一页(除非你决定仅在单页中获取元组)。因此应该以某种方式考虑并行查询的具体请。还有用于并行查询的特殊节点,所以如果我们想为向量化操作提供并行执行,我们还需要用自定义节点替换这个节点。

做的一些性能测试

Q1的结果:

max_parallel_workers_per_gather

PG9_6, enable_vectorize_engine=off

PG9_6, enable_vectorize_engine=on

master (jit=on)

0

36

20

10

4

10

--

5

9.6相比,PG13OLAP查询中提供了显著优势。当然并不意味着新版本的PG不需要向量化执行器。无论如何,我认为向量化执行器至于与列存结合才有意义。

Konstantin Knizhnik的测试

vectorize_engine移植到master。花费的时间比预期要长:executor代码中很多东西都发生了改变:

par.warkers

PG9_6矢量化=关闭

PG9_6矢量化=开启

矢量化=关闭jit=打开

矢量化=关闭jit=关闭

矢量化=onjit=ofn

矢量化=onjit=off

0

36

20

16

25.5

15

17.5

4

10

-

5

7

-

-

因此,它证明了JIT提供与向量化执行器计划相同的加速理论(这这都消除了解释开销,但方式不同)。我仍然不确定我们是否需要向量化执行器:因为与当前的JIT版本相比,标准heap几乎没有任何改进。但无论如何,我们将使用列存zedstorecstore对其进行测试。

列存的比较

par.workers

PG9_6vectorize=off

PG9_6vectorize=on

mastervectorize=offjit=on

mastervectorize=offjit=off

mastervectorize=onjit=on

mastervectorize=onjit=off

zedstore vectorize=offjit=on

zedstore vectorize=offjit=off

zedstore vectorize=onjit=on

zedstore vectorize=onjit=off

0

36

20

16

25.5

15

17.5

18

26

14

16

4

10

-

5

7

-

-

5

7

-

-

差距很小。

原文

https://postgrespro.com/list/id/CAB0yrenYmbYsioz167OrcO_8wVsvb=MA381-McLNcjEb1EJQYg@mail.gmail.com



推荐阅读
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 如何在php中将mysql查询结果赋值给变量
    本文介绍了在php中将mysql查询结果赋值给变量的方法,包括从mysql表中查询count(学号)并赋值给一个变量,以及如何将sql中查询单条结果赋值给php页面的一个变量。同时还讨论了php调用mysql查询结果到变量的方法,并提供了示例代码。 ... [详细]
  • Oracle分析函数first_value()和last_value()的用法及原理
    本文介绍了Oracle分析函数first_value()和last_value()的用法和原理,以及在查询销售记录日期和部门中的应用。通过示例和解释,详细说明了first_value()和last_value()的功能和不同之处。同时,对于last_value()的结果出现不一样的情况进行了解释,并提供了理解last_value()默认统计范围的方法。该文对于使用Oracle分析函数的开发人员和数据库管理员具有参考价值。 ... [详细]
  • 本文详细介绍了在ASP.NET中获取插入记录的ID的几种方法,包括使用SCOPE_IDENTITY()和IDENT_CURRENT()函数,以及通过ExecuteReader方法执行SQL语句获取ID的步骤。同时,还提供了使用这些方法的示例代码和注意事项。对于需要获取表中最后一个插入操作所产生的ID或马上使用刚插入的新记录ID的开发者来说,本文提供了一些有用的技巧和建议。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • 本文介绍了如何使用python从列表中删除所有的零,并将结果以列表形式输出,同时提供了示例格式。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • Oracle seg,V$TEMPSEG_USAGE与Oracle排序的关系及使用方法
    本文介绍了Oracle seg,V$TEMPSEG_USAGE与Oracle排序之间的关系,V$TEMPSEG_USAGE是V_$SORT_USAGE的同义词,通过查询dba_objects和dba_synonyms视图可以了解到它们的详细信息。同时,还探讨了V$TEMPSEG_USAGE的使用方法。 ... [详细]
  • 本文介绍了在MFC下利用C++和MFC的特性动态创建窗口的方法,包括继承现有的MFC类并加以改造、插入工具栏和状态栏对象的声明等。同时还提到了窗口销毁的处理方法。本文详细介绍了实现方法并给出了相关注意事项。 ... [详细]
  • MySQL中的MVVC多版本并发控制机制的应用及实现
    本文介绍了MySQL中MVCC的应用及实现机制。MVCC是一种提高并发性能的技术,通过对事务内读取的内存进行处理,避免写操作堵塞读操作的并发问题。与其他数据库系统的MVCC实现机制不尽相同,MySQL的MVCC是在undolog中实现的。通过undolog可以找回数据的历史版本,提供给用户读取或在回滚时覆盖数据页上的数据。MySQL的大多数事务型存储引擎都实现了MVCC,但各自的实现机制有所不同。 ... [详细]
  • Postgresql备份和恢复的方法及命令行操作步骤
    本文介绍了使用Postgresql进行备份和恢复的方法及命令行操作步骤。通过使用pg_dump命令进行备份,pg_restore命令进行恢复,并设置-h localhost选项,可以完成数据的备份和恢复操作。此外,本文还提供了参考链接以获取更多详细信息。 ... [详细]
  • 全面介绍Windows内存管理机制及C++内存分配实例(四):内存映射文件
    本文旨在全面介绍Windows内存管理机制及C++内存分配实例中的内存映射文件。通过对内存映射文件的使用场合和与虚拟内存的区别进行解析,帮助读者更好地理解操作系统的内存管理机制。同时,本文还提供了相关章节的链接,方便读者深入学习Windows内存管理及C++内存分配实例的其他内容。 ... [详细]
author-avatar
我家的表妹
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有