在Greenplum中实现公用表表达

时间:2013-03-09 01:41:00

标签: sql postgresql common-table-expression greenplum

有没有办法强制Greenplum PostgreSQL实现WITH子句中的子查询,如MATERIALIZEINLINE optimizer hints在Oracle中所做的那样?

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

2 个答案:

答案 0 :(得分:3)

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

如果您对查询执行了explain analyze,则会发现dept_count字词在单独的计划树中作为CTE Scan执行。它就像物化结果IIRC一样积累到了一个大都市。

更新:作者实际上正在使用Greenplum。对于Greenplum来说,上述陈述似乎并非如此,他们在PostgreSQL 8.2代码库之上实现了他们自己的CTE支持,或者对具有重大变化的8.4 CTE功能进行了非直接的反向移植。在Greenplum看起来你可能不得不使用临时表,除非有其他可用的Greenplum功能。

答案 1 :(得分: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 in the manual.

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

CTEs仅在他们所属的查询中可见。从来没有超越过。

单个查询专用的临时表

要将临时表的可见性限制为单个查询,请将它们放入事务中并添加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的临时表,因为无论如何都会回滚所有内容。