PostgreSQL公用表表达式与临时表?


11

WITHPostgreSQL文档显示以下示例:

WITH regional_sales AS (
        SELECT region, SUM(amount) AS total_sales
        FROM orders
        GROUP BY region
     ), top_regions AS (
        SELECT region
        FROM regional_sales
        WHERE total_sales > (SELECT SUM(total_sales)/10 FROM regional_sales)
     )
SELECT region,
       product,
       SUM(quantity) AS product_units,
       SUM(amount) AS product_sales
FROM orders
WHERE region IN (SELECT region FROM top_regions)
GROUP BY region, product;

它还指出:

WITH查询的一个有用属性是,即使父查询或同级WITH查询多次引用它们,每次执行父查询也只会对它们进行一次评估。

我看到它WITH可以用于其他方面,例如递归评估。但是在上面的示例中,使用WITH和创建临时表之间有什么重要区别吗?


当您使用CTE建立了查询,添加另一列SELECTWITH刚键入名称并重新运行。当使用临时表时,它将花费DROPCREATE。另一方面,如果您构建查询并且要多次重用静态数据,则使用索引构建临时表绝对有利于CTE。
Vao Tsun

如果使用@VaoTsun TEMPORARY TABLEON COMMIT DROP在查询中,它也只是一个修改查询并重新运行,右的事?postgresql.org/docs/9.6/static/sql-createtable.html
内森·朗

Answers:


16

有一些细微的差异,但没有什么太大的差异:

  • 您可以在临时表上添加索引;
  • 在会话的整个生命周期(或ON COMMIT DROP事务)中都存在临时表WITH始终严格限制查询的范围;
  • 如果查询调用的函数/程序,它可以看到临时表,但能不能看到任何WITH表表达式;
  • 临时表不会VACUUM在系统目录上生成工作WITH,它需要额外的往返时间来创建/填充它,并且需要在服务器的缓存管理中进行额外的工作,因此效率较低。

总体而言,WITH除非您知道将从索引中受益,否则您应该更喜欢临时表。

但是,另一个选项是子句中的子查询FROM,它具有一系列非常不同的优点。特别是可以内联,可以向上/向下推动预选赛。我在最近的博客文章中对此进行了撰写


关于视图和临时视图呢?
CMCDragonkai '16

1
介于两者之间,但比CTE术语更接近临时表。没有索引。会话范围。对功能/程序可见。需要目录真空。
Craig Ringer
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.