0

有没有办法强制Greenplum PostgreSQL在一个WITH子句中实现子查询,就像Oracle中MATERIALIZEINLINE 优化器提示在下面所做的那样?

WITH dept_count AS (
  SELECT /*+ MATERIALIZE */ deptno, COUNT(*) AS dept_count
  FROM   emp
  GROUP BY deptno)
SELECT ...

我已经搜索了一段时间,只是在 Oracle 中找到了这个功能。

我知道我可以使用CREATE TABLE AS,但是我有几个类似的查询,迫使我在每次查询后删除临时表,这非常不方便,而且可能效率低下。

更新:我测试了下表:

CREATE TABLE test (id: INT);

EXPLAIN WITH test2 AS (SELECT id FROM test)
SELECT COUNT(*) FROM test2;

                                 QUERY PLAN                                     
------------------------------------------------------------------------------------
Aggregate  (cost=0.36..0.37 rows=1 width=8)
   ->  Gather Motion 32:1  (slice1; segments: 32)  (cost=0.01..0.35 rows=1 width=8)
         ->  Aggregate  (cost=0.01..0.01 rows=1 width=8)
               ->  Subquery Scan test2  (cost=0.00..0.00 rows=1 width=0)
                     ->  Seq Scan on test  (cost=0.00..0.00 rows=1 width=4)

我正在使用 Greenplum Postgresql 8.2

4

2 回答 2

3

在 PostgreSQL 中,CTE 是强制实现 CTE 术语的优化障碍。这有望在未来的版本中改变,但如果有的话,将提供向后兼容性选项。

如果您explain analyze对查询执行 an ,您会发现该dept_count术语正在单独的计划树中作为CTE Scan. 它像物化结果一样累积到元组存储中,IIRC。

更新:作者实际上是在使用 Greenplum。上述声明对于 Greenplum 来说似乎并不正确,Greenplum 在 PostgreSQL 8.2 代码库之上实现了自己的 CTE 支持,或者对 8.4 CTE 特性进行了非直接的反向移植,并进行了重大更改。在 Greenplum 中,除非有额外的 Greenplum 特定功能可用,否则您可能必须使用临时表。

于 2013-03-09T02:05:21.703 回答
1

临时表

如果您正在寻找在会话期间持续存在的临时表,请使用实际的TEMPORARY TABLE.

CREATE TEMPORARY TABLE t AS
SELECT deptno, COUNT(*) AS dept_count
FROM   emp
GROUP  BY deptno;

SELECT ...
FROM t ...

CREATE [TEMPORARY] TABLE AS在手册中。

但是,PostgreSQL 中没有“全局”临时表。临时表仅对创建它的用户可见,并且仅在创建它的会话期间可见。

CTE仅在它们所属的查询中可见。永远不会超越。

单个查询专有的临时表

要将临时表的可见性限制为单个查询,请将它们放入事务中并添加ON COMMIT DROP,这会在事务结束时自动删除临时表:

BEGIN;
CREATE TEMP TABLE t ON COMMIT DROP AS
SELECT ...

我能想到的唯一用例,这是有意义的:如果你想在一个巨大的临时表上创建索引:

CREATE INDEX ON t(col1);

SELECT ..
FROM t ...;

ROLLBACK;

或者(在这里没有区别):

COMMIT;

如果您使用ROLLBACK,您也可以只使用临时表而不使用,ON COMMIT DROP因为无论如何都会回滚。

于 2013-03-09T01:48:16.900 回答