当前位置: 首页 > 编程日记 > 正文

PostgreSQL SQL 语言:并行查询

本文档为PostgreSQL 9.6.0文档,本转载已得到原译者彭煜玮授权。

1. 并行查询如何工作

当优化器判断对于某一个特定的查询,并行查询是最快的执行策略时,优化器将创建一个查询计划。该计划包括一个 Gather 节点。下面是一个简单的例子:


EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';QUERY PLAN                                      
-------------------------------------------------------------------------------------Gather  (cost=1000.00..217018.43 rows=1 width=97)Workers Planned: 2->  Parallel Seq Scan on pgbench_accounts  (cost=0.00..216018.33 rows=1 width=97)Filter: (filler ~~ '%x%'::text)
(4 rows)

在所有的情形下,Gather节点都只有一个子计划,它是将被并行执行的计划的一部分。如果 Gather节点 位于计划树的最顶层,那么整个查询将并行执行。如果它位于计划树的其他位置,那么只有查询的那一部分会并行执行。在上面的例子中,查询只访问了一个表,因此除Gather节点本身之外只有一个计划节点。因为该计划节点是 Gather节点的孩子节点,所以它会并行执行。

使用 EXPLAIN命令, 你能看到规划器选择的工作者数量。当查询执行期间到达Gather节点时,实现用户会话的进程将会请求和规划器选中的工作者数量一样多的后台工作者进程 。任何时候能够存在的后台工作者进程的总数由max_worker_processes限制,因此一个并行查询可能会使用比规划中少的工作者来运行,甚至有可能根本不使用工作者。最优的计划可能取决于可用的工作者的数量,因此这可能会导致不好的查询性能。如果这种情况经常发生,那么就应当考虑一下提高max_worker_processes的值,这样更多的工作者可以同时运行;或者降低max_parallel_workers_per_gather,这样规划器会要求少一些的工作者。

为一个给定并行查询成功启动的后台工作者进程都将会执行Gather 节点的后代计划的一部分。这些工作者的领导者也将执行该计划,不过它还有一个额外的任务:它还必须读取所有由工作者产生的元组。当整个计划的并行部分只产生了少量元组时,领导者通常将表现为一个额外的加速查询执行的工作者。反过来,当计划的并行部分产生大量的元组时,领导者将几乎全用来读取由工作者产生的元组并且执行Gather节点上层计划节点所要求的任何进一步处理。在这些情况下,领导者所作的执行并行部分的工作将会很少。

2. 何时会用到并行查询?

有几种设置会导致查询规划器在任何情况下都不生成并行查询计划。为了让并行查询计划能够被生成,必须配置好下列设置。

  • max_parallel_workers_per_gather必须被设置为大于零的值。这是一种特殊情况,更加普遍的原则是所用的工作者数量不能超过max_parallel_workers_per_gather所配置的数量。
  • dynamic_shared_memory_type必须被设置为除none之外的值。并行查询要求动态共享内存以便在合作的进程之间传递数据。

此外,系统一定不能运行在单用户模式下。因为在单用户模式下,整个数据库系统运行在单个进程中,没有后台工作者进程可用。

如果下面的任一条件为真,即便对一个给定查询通常可以产生并行查询计划,规划器都不会为它产生并行查询计划:

  • 查询要写任何数据或者锁定任何数据库行。如果一个查询在顶层或者 CTE 中包含了数据修改操作,那么不会为该查询产生并行计划。这是当前实现的一个限制,未来的版本中可能会有所改进。
  • 查询可能在执行过程中被暂停。只要在系统认为可能发生部分或者增量式执行,就不会产生并行计划。例如:用DECLARE CURSOR创建的游标将永远不会使用并行计划。类似地,一个FOR x IN query LOOP .. END LOOP形式的 PL/pgsql 循环也永远 不会使用并行计划,因为当并行查询进行时,并行查询系统无法验证循环中的代码执行起来是安全的。
  • 使用了任何被标记为PARALLEL UNSAFE的函数的查询。大多数系统定义的函数都被标记为PARALLEL SAFE,但是用户定义的函数默认被标记为PARALLEL UNSAFE。参见Section 15.4中的讨论。
  • 该查询运行在另一个已经存在的并行查询内部。例如,如果一个被并行查询调用的函数自己发出一个 SQL 查询,那么该查询将不会使用并行计划。这是当前实现的一个限制,但是或许不值得移除这个限制,因为它会导致单个查询使用大量的进程。
  • 事务隔离级别是可串行化。这是当前实现的一个限制。

即使对于一个特定的查询已经产生了并行查询计划,在一些情况下执行时也不会并行执行该计划。如果发生这种情况,那么领导者将会自己执行该计划在Gather节点之下的部分,就好像Gather节点不存在一样。上述情况将在满足下面的任一条件时发生:

  • 因为后台工作者进程的总数不能超过max_worker_processes,导致不能得到后台工作者进程。
  • 客户端发送了一个执行消息,并且消息中要求取元组的数量不为零。执行消息可见扩展查询协议中的讨论。因为libpq当前没有提供方法来发送这种消息,所以这种情况只可能发生在不依赖 libpq 的客户端中。如果这种情况经常发生,那在它可能发生的会话中设置 max_parallel_workers_per_gather是一个很好的主意,这样可以避免产生连续运行时次优的查询计划。
  • 事务隔离级别是可串行化。这种情况通常不会出现,因为当事务隔离级别是可串行化时不会产生并行查询计划。不过,如果在产生计划之后并且在执行计划之前把事务隔离级别改成可串行化,这种情况就有可能发生。

3. 并行计划

因为每个工作者只执行完成计划的并行部分,所以不可能简单地产生一个普通查询计划并使用多个工作者运行它。每个工作者都会产生输出结果集的一个完全拷贝,因而查询并不会比普通查询运行得更快甚至还会产生不正确的结果。相反,计划的并行部分一定被查询优化器在内部当作一个部分计划。也就是说,一定要这样来创建计划,使得每个将执行该计划的进程只产生输出行的一个子集,这样可以保证每个需要被输出的行刚好会被合作进程产生一次。

3.1. 并行扫描

当前唯一一种被修改用于并行查询的扫描类型是顺序扫描。因此在并行计划中的驱动表将总是被使用并行顺序扫描进行扫描。关系的块将被划分给合作进程。一次发放一个文件块,这样对于关系的访问仍然保持为顺序访问。在请求一个新页面之前,每一个进程将访问分配给它的页面上的每一个元组。

3.2. 并行连接

驱动表将被使用嵌套循环或者哈希连接连接到一个或者多个其他表。在连接的外侧可以是任何一种被规划器支持可以安全地在并行工作者中运行的非并行计划。例如,它可以是一个索引扫描,基于从内表取得的一列来查找值。每个工作者都将会完整地执行外侧的计划,这也是为什么这里不能支持归并连接的原因。归并连接的外侧常常涉及到排序整个内表,即便使用索引,多次在内表上进行完全索引扫描也效率不高。

3.3. 并行聚集

将查询的聚集部分整个地并行执行是不可能的。例如,如果一个查询涉及到选择COUNT(*),每个工作者可以计算一个总和,但是这些总和需要被整合在一起以产生最终的答案。如果一个计划涉及到GROUP BY子句,为每个组需要计算出一个单独的总和。即使聚集不能完全地并行执行,但是涉及聚集的查询常常是并行查询很好的候选,因为它们通常都是读很多行但只返回少数几行给客户端。返回很多行给客户端的查询常常受制于客户端读取数据的速度,这种情况下并行查询帮助不大。

PostgreSQL通过做两次聚集来支持并行聚集。第一次,每个参与查询计划并行部分执行的进程执行一个聚集步骤,为进程发现的每个分组产生一个部分结果。这在计划中反映为一个PartialAggregate节点。第二次,部分结果被通过Gather节点传输给领导者。最后,领导者对所有工作者的部分结果进行重聚集以得到最终的结果。这在计划中反映为一个FinalizeAggregate节点。

并行聚集并不能支持所有的情况。每个聚集对于并行机制一定要是安全的,并且必须有一个结合函数。如果聚集有一个internal类型的转移状态,它必须有序列化和反序列化函数。对于有序集聚集或者查询涉及GROUPING SETS时不支持并行聚集。只有当查询中涉及的所有连接也是计划中并行不分的一部分时,才能使用并行聚集。

3.4. 并行计划小贴士

如果我们想要一个查询能产生并行计划但事实上又没有产生,可以尝试减小parallel_setup_cost或者parallel_tuple_cost。当然,这个计划可能比规划器优先产生的顺序计划还要慢,但也不总是如此。如果将这些设置为很小的值(例如把它们设置为零)也不能得到并行计划,那就可能是有某种原因导致查询规划器无法为你的查询产生并行计划。

在执行一个并行计划时,可以用EXPLAIN (ANALYZE,VERBOSE)来显示每个计划节点在每个工作者上的统计信息。这些信息有助于确定是否所有的工作被均匀地分发到所有计划节点以及从总体上理解计划的性能特点。

4. 并行安全性

规划器把查询中涉及的操作分类成并行安全、并行受限或者并行不安全。并行安全的操作不会与并行查询的使用产生冲突。并行受限的操作不能在并行工作者中执行,但是能够在并行查询的领导者中执行。因此,并行受限的操作不能出现在Gather节点之下,但是能够出现在包含有Gather 节点的计划的其他位置。并行不安全的操作不能在并行查询中执行,甚至不能在领导者中执行。当一个查询包含任何并行不安全操作时,并行查询对这个查询是完全被禁用的。

下面的操作总是并行受限的。

  • 公共表表达式(CTE)的扫描。
  • 临时表的扫描。
  • 外部表的扫描,除非外部数据包装器有一个IsForeignScanParallelSafe API。
  • 对InitPlan或者SubPlan的访问。

4.1. 为函数和聚集加并行标签

规划器无法自动判定一个用户定义的函数或者聚集是并行安全、并行受限还是并行不安全,因为这需要预测函数可能执行的每一个操作。一般而言,这就相当于一个停机问题,因此是不可能的。甚至对于可以做到判定的简单函数我们也不会尝试,因为那会非常昂贵而且容易出错。相反,除非是被标记出来,所有用户定义的函数都被认为是并行不安全的。在使用CREATE FUNCTION或者ALTER FUNCTION时,可以通过指定PARALLEL SAFE、PARALLEL RESTRICTED或者PARALLEL UNSAFE来设置标记 。在使用CREATE AGGREGATE时,PARALLEL选项可以被指定为SAFE、RESTRICTED或者 UNSAFE。

如果函数和聚集会写数据库、访问序列、改变事务状态(即便是临时改变,例如建立一个EXCEPTION块来捕捉错误的 PL/pgsql)或者对设置做持久化的更改,它们一定要被标记为PARALLEL UNSAFE。类似地,如果函数会访问临时表、客户端连接状态、游标、预备语句或者系统无法在工作者之间同步的后端本地状态,它们必须被标记为PARALLEL RESTRICTED。例如,setseed和 random由于后一种原因而是并行受限的。

一般而言,如果一个函数是受限或者不安全的却被标记为安全,或者它实际是不安全的却被标记为受限,把它用在并行查询中时可能会抛出错误或者产生错误的回答。如果 C 语言函数被错误标记,理论上它会展现出完全不明确的行为,因为系统中无法保护自身不受任意 C 代码的影响。但是,在最有可能的情况下,结果不会比其他任何函数更糟糕。如果有疑虑,最好还是标记函数为UNSAFE。

如果在并行工作者中执行的函数要求领导者没有持有的锁,例如读该查询中没有引用的表,那么工作者退出时会释放那些锁(而不是在事务结束时释放)。如果你写了一个这样做的函数并且这种不同的行为对你很重要,把这类函数标记为PARALLEL RESTRICTED以确保它们只在领导者中执行。

注意查询规划器不会为了获取一个更好的计划而考虑延迟计算并行受限的函数或者聚集。所以,如果一个被应用到特定表的WHERE子句是并行受限的,查询规划器就不会考虑把对那张表的扫描放置在Gather节点之下。在一些情况中,可以(甚至效率更高)把对表的扫描包括在查询的并行部分并且延迟对WHERE子句的计算,这样它会出现在Gather节点之上。不过,规划器不会这样做。

相关文章:

常用的linux的命令行操作

2019独角兽企业重金招聘Python工程师标准>>> 系统信息 arch 显示机器的处理器架构(1) uname -m 显示机器的处理器架构(2) uname -r 显示正在使用的内核版本 dmidecode -q 显示硬件系统部件 - (SMBIOS / DMI) hdparm -i /dev/hda 罗列一个磁盘的架构特性 hdparm -tT …

Python 极简实现 IoU

来源 | 简明AI头图 | 下载于视觉中国出品 | AI 科技大本营(ID:rgznai100)IOU中文名叫交并比,见名知意就是交集与并集的比值。是在目标检测中常用的算法。IoU原理如上图所示,就是计算上面阴影部分与下面阴影部分的比值。…

静态页htm传参数

//从转向过来的URL中截取参数 开始function SplitUrl(key){var fstrkey;var getstr;var urldocument.URL.toString();urlurl.toLowerCase();//转为小写var locurl.indexOf(fstr);if(loc>0){getstrurl.substring(locfstr.length,url.length);return getstr;}else{return &quo…

vue router 入门笔记

vue router 入门笔记 tips: components优先级大于component,即当一个route对象里同时配置了component和components时component视为无效即使route对象有name属性,也要配置一个path属性。name属性只是配对用的,path是要直接打到url上…

用C#的Raw Socket实现网络封包监视

<script language"javascript" src"/ad/js/edu_left_300-300.js" type"text/javascript"></script> 谈起socket编程&#xff0c;大家也许会想起QQ和IE&#xff0c;没错。还有许多网络工具如P2P、NetMeeting等在应用层实现的应用程序…

人工智能是否能开启人类世界新纪元?

想必许多人都不止一次地幻想过&#xff0c;当人工智能发展到极限时&#xff0c;它将为我们的生活带来多少触手可及的便捷&#xff0c;或是意想不到的惊喜呢&#xff1f;试想一下我们身处英剧《黑镜》的世界中&#xff0c;人类的生活里充斥着人工智能对社交行为的各种评分机制&a…

1月国内操作系统市场:Windows XP份额高达60.84%

IDC评述网&#xff08;idcps.com&#xff09;02月21日报道&#xff1a;据CNZZ数据&#xff0c;在国内操作系统市场上&#xff0c;2014年1月份&#xff0c;微软Windows系统依旧称霸市场&#xff0c;份额为90.63%&#xff0c;环比去年末下滑0.57%。对于市场份额下滑一事&#xff…

17.08.17

控制文件 丢失部分控制文件&#xff1a; SQL> select * from v$controlfile; $ >/u01/app/oracle/oradata/orcl/control01.ctl SQL> select * from v$tablespace; 报错 SQL> alter system checkpoint; 报错 $ vi /u01/app/oracle/diag/rd…

用C#实现基于TCP协议的网络通讯

TCP协议是一个基本的网络协议&#xff0c;基本上所有的网络服务都是基于TCP协议的&#xff0c;如HTTP,FTP等等&#xff0c;所以要了解网络编程就必须了解基于TCP协议的编程。然而TCP协议是一个庞杂的体系&#xff0c;要彻底的弄清楚它的实现不是一天两天的功夫&#xff0c;所幸…

Java NIO系列教程(二) Channel

为什么80%的码农都做不了架构师&#xff1f;>>> Java NIO的通道类似流&#xff0c;但又有些不同&#xff1a; 既可以从通道中读取数据&#xff0c;又可以写数据到通道。但流的读写通常是单向的。通道可以异步地读写。通道中的数据总是要先读到一个Buffer&#xff0…

百度CTO王海峰博鳌解读AI“融合创新”,算力算法数据发挥综合作用

4月18至21日&#xff0c;博鳌亚洲论坛2021年年会在海南博鳌举行。19日下午&#xff0c;百度CTO王海峰受邀参加本届博鳌年会“后疫情时代的人工智能”为主题的圆桌论坛。与公钥加密技术之父、图灵奖得主惠特菲尔德迪菲&#xff0c;阿斯利康公司董事长雷夫约翰森等多位专家和企业…

Java开发工具(Eclipse中内容辅助键的使用)

* A:Alt/ 起提示作用* B:mainalt/,sysoalt/,给出其他提示* C:补充输出语句,选中需要输出的部分,alt/选择最后一项即可* C:定义自己的alt / * windows--perference-Java-Editor-Templates--New * A:新建 ctrl n(new)* B:格式化 ctrlshiftf(format)* C:导入包 ctrlshifto *…

常用的css3的新属性

2019独角兽企业重金招聘Python工程师标准>>> 作为前端开发人员&#xff0c;如果你还不知道或还没有接触过CSS3&#xff0c;那么你真的OUT了&#xff01;就像蒸汽机的发明标志工业革命的开始一样&#xff0c;CSS3和HTML5的出现&#xff0c;将会带来WEB前端开发以及互…

高效分页存储过程

存储过程与页面调用如下&#xff1a; CREATE PROCEDURE search_sptblName varchar(255), -- 表名 strGetFields varchar(1000) *, -- 需要返回的列 fldName varchar(255), -- 排序的字段名 PageSize int 10, -- 页尺寸 PageIndex int , -- 页码 doCount bit 0, -- 返回记录…

2020年企业业务营收同比增长23.0%,华为的数字化转型实践之道

近日&#xff0c;在华为分析师大会期间&#xff0c;华为举办“共创行业新价值”主题峰会&#xff0c;与来自全球的400多名行业分析师、财经分析师、各行业意见领袖及媒体现场参会&#xff0c;分享了对行业趋势的洞察&#xff0c;解决方案在具体行业场景中的实践与探索&#xff…

Neo4j - CQL简介

CQL代表Cypher查询语言。 像Oracle数据库具有查询语言SQL&#xff0c;Neo4j具有CQL作为查询语言。 Neo4j CQL - 它是Neo4j图形数据库的查询语言。它是一种声明性模式匹配语言它遵循SQL语法。它的语法是非常简单且人性化、可读的格式。常用的Neo4j CQL命令&#xff1a; NO.CQL…

String.Format格式说明

C#格式化数值结果表 字符 说明 示例 输出 C货币string.Format("{0:C3}", 2)&#xff04;2.000D十进制string.Format("{0:D3}", 2)002E科学计数法1.20E0011.20E001G常规string.Format("{0:G}", 2)2N用分号隔开的数字string.Format("{…

Azure 中国四年扩容 12 倍还不够,微软放话:全球每年新建 50-100 数据中心!

作者 | 伍杏玲出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;数据已渗透到我们生活和工作的方方面面&#xff0c;如今全球正处于经济发展转型与变革的关键时期&#xff0c;数据作为数字经济的核心生产要素&#xff0c;无疑建设先进的数据中心是科技企业的硬核 IT 实…

.NET中多线程的使用

为什么80%的码农都做不了架构师&#xff1f;>>> 1、不需要传递参数&#xff0c;也不需要返回参数。启动一个线程最直观的办法是实用Thread类。 2、ThreadStart类型的委托&#xff0c;这个委托制定了线程需要执行的方法&#xff1a;method。ThreadStart这个委托定义…

[数位dp] spoj 10738 Ra-One Numbers

题意&#xff1a;给定x、y。为[x,y]之间有多少个数的偶数位和减去奇数位和等于一。个位是第一位。 样例&#xff1a; 101-01 所以10是这种数 思路&#xff1a;数位dp[i][sum][ok] i位和为sum 是否含有前导0. 然后就是由于有负数 所以依据范围把0设置为100 然后最后和等于101则为…

VML 画统计 柱状、饼图、折线

<!-- --><!-- 涉及文件 alt.js / function.asp--><!-- 必须包含页面所有代码 --><!-- 高度定义有待改进 chart_top --> <html xmlns:v"urn:schemas-microsoft-com:vml" xmlns:o"urn:schemas-microsoft-com:office:office">…

在Ubuntu下FFmpeg编译,支持x264和x265(HECV)

所有下载的源在Ubuntu下FFmpeg编译&#xff0c;支持x264和x265。Ubuntu 12.04FFmpeg 2.1 Release 注意&#xff1a;cmake要升级要2.8.8yasm要升级到1.2.00000. 资料&#xff1a;http://stackoverflow.com/questions/19634453/ffmpeg-how-to-generate-a-mp4-with-h-265-codecFF…

Java 程序员薪资这么高,取决于什么?

众多行业中&#xff0c;程序员当然属于高薪职业。无论是国内还是国外&#xff0c;IT行业的程序员、工程师&#xff0c;甚至连码农都要比其他行业的从业者的收入高很多&#xff01;但是Java程序员拿多少钱跟有多少经验有关系&#xff0c;但经验的多少跟年限没有必然关系。工作以…

极品:蓝丽网 - Vml图像画板.2003 web上的PhotoShop

<HTML xmlns:v><HEAD><META http-equiv"Content-Type" content"text/html; Charsetgb2312"><META name"GENERATOR" content"网络程序员伴侣(Lshdic)2004"><META name"GENERATORDOWNLOADADDRESS"…

库克踏春而来,小而美的 iPhone 全新配件问世

整理 | 苏宓出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;从乔布斯时代的「不要问消费者想要什么&#xff0c;一个企业的目标就是去创造那些消费者需要但无法形容和表达的需求」&#xff0c;到库克心中的「创新不一定是改变&#xff0c;而是做得更好」&#xff0…

嵌入式实现 微信网页版 群发信息。

为什么80%的码农都做不了架构师&#xff1f;>>> webchatHelper 一个微信群发信息的chrome扩展 咦&#xff0c;动态图片发不出&#xff1f; http://github.com/think2011/webchatHelper/raw/master/img/demo.gif 杂乱的源码地址&#xff1a;https://github.com/thi…

linux 在执行命令过程中,反单引号(`)这个符号代表的意义为何?

在一串命令中&#xff0c;在之内的命令将会被先执行&#xff0c;而且执行出来的结果将作为外部的输入信息。例如&#xff1a;uname -r 会显示出目前的内核版本&#xff0c;而我们的内核版本在/lib/modules里面&#xff0c;因此。你可以先执行uname -r 找出内核版本&#xff0c;…

C#精髓【月儿原创】第二讲 WMI完美秀出CPU编号厂商主频百分比等全部信息

说明&#xff1a;准备出一个系列&#xff0c;所谓精髓讲C#语言要点。这个系列没有先后顺序&#xff0c;不过尽量做到精。可能会不断增删整理&#xff0c;本系列最原始出处是csdn博客,谢谢关注。 C#精髓 第二讲 WMI完美秀出CPU编号厂商主频电压等全部信息 作者&#xff1a;清…

联邦学习,为何而生?

隐私数据是否早已泄露&#xff0c;而我们却毫无察觉&#xff1f;随着大数据、边缘计算、大型云计算平台和各种开源框架的发展&#xff0c;机器学习等人工智能技术以前所未有的速度应用到各个行业&#xff0c;人工智能技术带来了新的挑战&#xff0c;数据的隐私和安全引起了全世…

css控制非固定文本自动换行

不知道为什么一直记不住这个属性&#xff0c;趁有时间整理了下下&#xff01; 强制不换行p.www_52css_com {  white-space:nowrap;  } 自动换行p.www_52css_com {   word-wrap: break-word;   word-break: normal;   } 强制英文单词断行p.www_52css_com {  word-br…