Postgres 9.6 并行 XPath

Posted

技术标签:

【中文标题】Postgres 9.6 并行 XPath【英文标题】:Postgres 9.6 parallel XPath 【发布时间】:2017-06-07 12:06:16 【问题描述】:

我已经设置了 Postgres 9.6 并检查了并行查询正在工作的随机整数的大表。 但是,对另一个表的 XML 列的简单 XPath 查询始终是顺序的。在 Postgres 中,这两个 XPath 函数都被标记为并行安全的。我试图改变 XPath 成本,因此预期成本猛增,但并没有改变任何东西。 我错过了什么?

示例表 DDL: CREATE TABLE "test_table" ("xml" XML );

查询示例: SELECT xpath('/a', "xml") FROM "test_table";

示例数据: <a></a>。 请注意,真实数据包含大小为 10-1000kB 的 XML。

> select pg_size_pretty(pg_total_relation_size('test_table'));
28 MB

> explain (analyze, verbose, buffers) select xpath('/a', "xml") from test_table;
Seq Scan on public.test_table  (cost=0.00..64042.60 rows=2560 width=32) (actual time=1.420..4527.061 rows=2560 loops=1)
  Output: xpath('/a'::text, xml, ''::text[])
  Buffers: shared hit=10588
Planning time: 0.058 ms
Execution time: 4529.503 ms

【问题讨论】:

请发布您正在运行的查询,最好是表结构(可以简化)和一些示例数据。 -- 请注意,1 个函数(不是并行安全的)足以选择退出整个查询的并行性。 嗯,没有比这更简单的了,但我按照你的要求添加了它。 Edit您的问题并添加使用explain (analyze, verbose)生成的执行计划。 Formatted text 请no screen shots 表可能太小而无法考虑进行并行 seq 扫描。 default minimum size 是 8MB。但是,对只有 2500 行的表进行 3 秒的 seq 扫描太慢了。那是一张非常宽的桌子吗?即它有很多列吗?使用 explain (analyze, buffers) 可能会给出提示 尝试删除parallel_tuple_costparallel_setup_cost 的值。将它们设置为零应该使计划者选择并行计划。为您的查询计时,看看计划者是否真的弄错了。根据我的经验,parallel_tuple_cost 可能会因为默认值 (0.1) 太高而超出返回大量行的查询的估计值。 【参考方案1】:

这里的相关点可能是“关系大小”和“总关系大小”之间的区别:

CREATE TABLE test_table AS
  SELECT ('<a>' || repeat('x', 1000000) || '</a>')::xml AS "xml"
  FROM generate_series(1, 2560);

SELECT
  pg_size_pretty(pg_relation_size('test_table')) AS relation_size,
  pg_size_pretty(pg_total_relation_size('test_table')) AS total_relation_size;

 relation_size | total_relation_size
---------------+---------------------
 136 kB        | 30 MB

像这样的大列值不会存储在主关系中,而是推送到其关联的TOAST table。此外部存储不计入pg_relation_size(),这是优化器在评估并行计划时似乎与min_parallel_relation_size 进行比较的内容:

SET parallel_setup_cost = 0;
SET parallel_tuple_cost = 0;
SET min_parallel_relation_size = '144kB';
EXPLAIN SELECT xpath('/a', "xml") FROM test_table;

                          QUERY PLAN
---------------------------------------------------------------
 Seq Scan on test_table  (cost=0.00..49.00 rows=2560 width=32)
SET min_parallel_relation_size = '136kB';
EXPLAIN SELECT xpath('/a', "xml") FROM test_table;

     QUERY PLAN
------------------------------------------------------------------------------
 Gather  (cost=0.00..38.46 rows=2560 width=32)
   Workers Planned: 1
   ->  Parallel Seq Scan on test_table  (cost=0.00..35.82 rows=1506 width=32)

【讨论】:

奇怪 - 我完全重复了你的步骤,但最终的查询计划与前一个相同,顺序。此外,您的查询计划有Workers Planned: 1 也很奇怪。您确定您没有在运行两个最后一个查询或提供的查询之间不小心设置了 force_parallel_mode 吗? 请忽略我对force_parallel_mode 的评论——当relation_size 接近min_parallel_relation_size 时,我也只有1 个工人。添加更多信息:并行查询肯定适用于我的设置。当使用包含真实数据的表时,SELECT char_length("name") FROM real_table 等简单查询将在您的 SET ... 查询之后并行运行。但是运行SELECT xpath('/a', "xml") FROM real_table 仍然会导致顺序查询。值得一提的是,Postgres 版本是 9.6.3。 啊,那只是我愚蠢。测试时,我将 xpath(text, xml, text[]) 的成本设置为 10000,但我记得仅将 xpath(text, xml) 的成本重置为 1。现在它出于某种原因阻止了 Postgres 使用并行计划。显然,我根本不明白成本是如何运作的,但那是另一回事。感谢您的精彩回答!

以上是关于Postgres 9.6 并行 XPath的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Homebrew 将 Postgis 安装到 Postgres@9.6 的 Keg 安装中?

postgres 9.6 新的进度报告工具

在 Postgres 9.6 中创建数据透视表

Postgres 9.6 如何遍历数组并将每个数组值插入表中?

如何在 Postgres 9.6+ 中生成长度为 N 的随机、唯一的字母数字 ID?

如何在Debian 8/7上安装PostgreSQL 9.6