AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / user-239166

peremeykin's questions

Martin Hope
peremeykin
Asked: 2021-11-06 01:55:14 +0800 CST

PostgreSQL:在查询计划中实现为 Merge Join 的内部节点

  • 3

我正在学习 PostgreSQL EXPLAIN 计划节点。目前,我正在研究 Materialize 节点。这是我在博文(https://www.depesz.com/2013/05/09/explaining-the-unexplainable-part-3/)中找到的一个查询和我自己获得的一个计划(从结构上讲,它是与博客文章中的相同):

set work_mem= '1GB';
explain analyze select * from
(select * from pg_class order by oid) as c
join
(select * from pg_attribute a order by attrelid) as a
on c.oid = a.attrelid;
                                                                              QUERY PLAN                                                                              
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Merge Join  (cost=34.27..333.37 rows=2913 width=504) (actual time=0.823..28.413 rows=2913 loops=1)
   Merge Cond: (pg_class.oid = a.attrelid)
   ->  Sort  (cost=33.99..34.97 rows=395 width=265) (actual time=0.739..1.084 rows=395 loops=1)
         Sort Key: pg_class.oid
         Sort Method: quicksort  Memory: 130kB
         ->  Seq Scan on pg_class  (cost=0.00..16.95 rows=395 width=265) (actual time=0.038..0.285 rows=395 loops=1)
   ->  Materialize  (cost=0.28..257.05 rows=2913 width=239) (actual time=0.060..11.702 rows=2913 loops=1)
         ->  Index Scan using pg_attribute_relid_attnum_index on pg_attribute a  (cost=0.28..220.63 rows=2913 width=239) (actual time=0.050..6.827 rows=2913 loops=1)
 Planning Time: 1.472 ms
 Execution Time: 29.617 ms
(10 rows)

我无法理解博客作者关于 Postgres 为何在这里使用 Materialize 的论点。

...合并连接必须匹配几个条件。有些是显而易见的(必须对数据进行排序),有些则不那么明显,因为技术性更强(数据必须可以来回滚动)。

正因为如此(这些不是那么明显的标准),有时 Pg 必须将来自源的数据(在我们的例子中是索引扫描)具体化,以便在使用时具有所有必要的功能。

为什么 Merge Join 需要数据可以来回滚动?根据我对 Merge Join 的理解,它使用两个指针同时迭代两个数据集。Merge Join 算法在向后退时没有案例。无论如何,据我了解,索引扫描实际上是“可前后滚动”的。我多次看到“Index Scan Backward”。那么为什么 Postgres 必须实现它呢?

我在其他来源,即Korry Douglas 和 Susan Douglas的旧书“ PostgreSQL:构建、编程和管理 PostgreSQL 数据库的综合指南”,第 2 版中找到了博客作者观点的确认:

Materialize 也将用于一些合并连接操作。特别是,如果 Merge Join 运算符的内部输入集不是由 Seq Scan、Index Scan、Sort 或 Materialize 运算符生成的,则计划器/优化器将在计划中插入 Materialize 运算符。这条规则背后的原因并不明显,它更多地与其他操作员的能力有关,而不是与您的数据的性能或结构有关。Merge Join 运算符很复杂;Merge Join 的一项要求是输入集必须按连接列排序。第二个要求是内部输入集必须是可重新定位的;也就是说,Merge Join 需要在输入集中前后移动。并非所有有序运算符都可以前后移动。如果内部输入集是由一个不可重定位的算子产生的,

在我的例子中,内部输入集是由 Index Scan 产生的,所以根据本书,这个计划中应该没有 Materialize 节点。

然后我决定修改查询,使规划器不会使用 Materialize,但 Merge Join 仍然存在。这就是我想出的:

set enable_hashjoin = off;
set work_mem= '1GB';
explain analyze select * from
(select * from pg_class order by oid) as c
join
(select * from pg_attribute a) as a
on c.oid = a.attrelid;
                                                                           QUERY PLAN                                                                           
----------------------------------------------------------------------------------------------------------------------------------------------------------------
 Merge Join  (cost=34.27..296.96 rows=2913 width=504) (actual time=0.554..10.103 rows=2913 loops=1)
   Merge Cond: (pg_class.oid = a.attrelid)
   ->  Sort  (cost=33.99..34.97 rows=395 width=265) (actual time=0.491..0.645 rows=395 loops=1)
         Sort Key: pg_class.oid
         Sort Method: quicksort  Memory: 130kB
         ->  Seq Scan on pg_class  (cost=0.00..16.95 rows=395 width=265) (actual time=0.021..0.177 rows=395 loops=1)
   ->  Index Scan using pg_attribute_relid_attnum_index on pg_attribute a  (cost=0.28..220.63 rows=2913 width=239) (actual time=0.041..2.296 rows=2913 loops=1)
 Planning Time: 1.188 ms
 Execution Time: 10.731 ms
(9 rows)

我从第二个子查询中删除order by attrelid并强行禁用了 Hash Join。除了 Materialize 节点外,此计划与上一个计划相同。因此,我得出结论,Merge Join 不是规划器在上一个中使用 Materialize 的原因。这个计划比较便宜,但我想结果是一样的。

如果您能帮助我解决其中的一些难题,我将不胜感激:

  1. Merge Join 真的需要能够向后迭代内部数据集吗?在哪些情况下?就 Merge Join 要求而言,Index Scan 的结果是否“向后迭代”?
  2. 为什么 Postgres 计划器在第一个计划中使用 Materialize,即使它成本更高?它在这里服务的目的是什么?为什么 Postgres planner 在第二个计划中不使用 Materialize?
postgresql query-performance
  • 2 个回答
  • 454 Views

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve