只有通过顺序扫描访问驱动表的严格只读查询才能并行化。
我的问题是:如果CTE(WITH
子句)仅包含读取操作,但其结果用于提供写入操作(如插入或更新),是否也不允许并行执行顺序扫描?
我的意思是,由于CTE非常类似于仅用于当前正在执行的查询的临时表,我是否可以假设其内部查询可以利用PostgreSQL 9.6的全新并行seq-scan?否则,是否将其视为正在使用的子查询并且无法执行并行扫描?
例如,考虑以下查询:
WITH foobarbaz AS (
SELECT foo FROM bar
WHERE some_expensive_function(baz)
)
DELETE FROM bar
USING foobarbaz
WHERE bar.foo = foobarbaz.foo
;
Run Code Online (Sandbox Code Playgroud)
该foobarbaz计算是否有望实现并行化,还是由于删除语句而被禁止?
如果不允许,我认为可以用CREATE TEMPORARY TABLE语句代替CTE 。但是我想我会陷入与CREATE TABLE是写操作相同的问题。我错了吗?
最后,我可以尝试的最后一次机会是将其作为纯读取操作执行,并将其结果用作插入和/或更新操作的输入。在事务之外,它应该工作。但是问题是:如果读取操作和插入/更新在a begin
和commit
句子之间,则仍然不允许这样做吗?我了解它们是两个完全不同的操作,但与Postgres在同一事务中。
明确地说,我担心的是,我有大量难以理解和难以重新设计的SQL查询,这些查询涉及具有低性能函数调用的多个顺序扫描,并对两个表执行复杂的更改。整个过程在一个事务中运行,因为如果不这样做,失败时的混乱将是完全不可恢复的。
我希望能够并行化一些顺序扫描,以利用计算机的8个cpu内核来更快地完成该过程。
请不要回答我需要完全重新设计该烂摊子:我知道并且我正在研究它。但这是一个伟大的项目,我们需要同时继续工作。
无论如何,任何建议都会令人感激。
编辑:
我添加了一份简短的报告,介绍了到目前为止我可以发现的内容:
正如@a_horse_with_no_name在他的评论中说的(谢谢),CTE和查询的其余部分是单个DML语句,并且,如果它具有写操作,即使在CTE之外,那么CTE也无法并行化(我也对其进行了测试) 。
另外,我在此Wiki页面上找到了比并行发行版链接更简洁的并行扫描信息。
由于该Wiki页面,我可以检查的一个有趣的点是,我需要将涉及的函数声明为并行安全。我做到了并且工作了(在没有文字的测试中)。
另一个有趣的地方是@a_horse_with_no_name在他的第二条评论中所说的:使用DbLink执行纯只读查询。但是,对此进行了一些调查,我发现postgres_fdw(在Wiki中明确提到不支持并行扫描)使用更现代且符合标准的基础架构提供了大致相同的功能。
最后,我检查了是否可以在事务内部的只读查询中执行并行扫描,即使该事务稍后执行写操作(不会触发异常并且我可以提交)。
...总而言之,我认为我最好的选择(如果不是唯一的选择)将是重构脚本,以便在以后在同一事务中执行写入操作之前将数据读取到内存中。
它将增加I / O开销,但参加我管理的延迟会更好。
我想知道是否有办法根据活动会话临时更改 tmux 前缀。
我使用 tmux 管理多个会话,以便在本地桌面上处理不同的任务或项目。但有时我需要在远程系统上工作,在远程系统上打开多个窗格、窗口甚至不同的会话也很有用。
在本地 tmux 中打开远程 tmux 会话效果很好,但每次我想发出(远程)tmux 命令时,我都需要按两次前缀键(我有一个地图可以在双击时发送自身)。
这非常烦人,因为大多数时候我最终会无意中将其发送到本地 tmux。
如果我可以仅更改给定会话的本地前缀(或者至少在该会话处于活动状态时),那就太好了。
暂时禁用它也可能就足够了,因为我可以定义一个备用前缀,仅在主前缀被禁用时才使用它。
任何建议都会受到欢迎。