CTE上的并行查询,用于在PostgreSQL中编写操作

时间:2016-10-13 08:25:23

标签: postgresql postgresql-9.6 postgresql-parallel-query

来自PostgreSQL 9.6 Release Notes

  

只有通过顺序扫描访问驱动表的严格只读查询才能并行化。

我的问题是:如果CTE(WITH子句)仅包含读取操作,但其结果用于提供写入操作(如插入或更新),是否也不允许并行化顺序扫描?< / p>

我的意思是,由于CTE很像一个只存在于当前正在执行的查询的临时表,我可以假设它的内部查询可以利用PostgreSQL 9.6的全新并行seq扫描?或者,它是否被视为使用子查询并且无法执行并行扫描?

例如,请考虑以下问题:

WITH foobarbaz AS (
  SELECT foo FROM bar
  WHERE some_expensive_function(baz)
)
DELETE FROM bar
USING foobarbaz
WHERE bar.foo = foobarbaz.foo
;

foobarbaz计算是否可以并行化或因为删除句子而被禁止?

如果不允许,我认为可以用 CREATE TEMPORARY TABLE 语句替换CTE。但我认为我会陷入同样的​​问题,因为 CREATE TABLE 是一个写操作。我错了吗?

最后,我可以尝试的最后一次机会是将其作为纯读取操作执行,并将其结果用作插入和/或更新操作的输入。在交易之外它应该工作。但问题是:如果读取操作和插入/更新是在begincommit个句子之间,那么它是否会被允许?我知道他们是两个完全不同的操作,但是在同一个交易中和Postgres。

要明确的是,我担心的是,我有大量难以阅读且难以重新设计的SQL查询,这些查询涉及使用低性能函数调用的多个顺序扫描,并且对两个表执行复杂的更改。整个过程在一个单独的交易中运行,因为如果不是这样,那么在发生故障时的混乱将是完全无法恢复的。

我希望能够并行化一些顺序扫描,以利用机器的8个cpu核心来更快地完成这个过程。

请不要回答我需要完全重新设计这个烂摊子:我知道并且我正在努力。但这是一个伟大的项目,我们需要继续努力。

无论如何,任何建议都会感激不尽。

修改

我添加了一份关于我现在能发现的内容的简短报告:

  • 正如@a_horse_with_no_name在他的评论中所说的那样(感谢),CTE和查询的其余部分是单个DML语句,如果它有写操作,甚至在CTE之外,则CTE无法并行化(我也测试了它。)

  • 此外,我发现此wiki page提供了有关并行扫描的更简洁信息,而不是我在发行说明链接中找到的信息。

  • 感谢wiki页面,我可以查看一个有趣的观点,我需要将所涉及的函数声明为 parallel safe 。我做到了并且工作了(在没有着作的测试中)。

  • 另一个有趣的观点是@a_horse_with_no_name在他的第二条评论中说:使用DbLink执行纯只读查询。但是,稍微调查一下,我看到postgres_fdw,在wiki中明确提到为非支持并行扫描,provides roughly the same functionality using a more modern and standards-compliant infrastructure

    • 而且,另一方面,即使它会起作用,我最终也会从交易之外获取数据,在某些情况下我会接受,但我认为,这不是一般解决方案的好主意。 / LI>
  • 最后,我检查了可以在事务中的只读查询内部执行并行扫描,即使它稍后执行写操作(没有异常被触发而且我可以承诺)。

...总之,我认为我最好的选择(如果不是唯一一个)将重构脚本,以便在将数据读取到内存之后再在同一事务中执行写操作。

它会增加I / O开销,但是,考虑到我管理它的延迟会更好。

0 个答案:

没有答案