AnalyticDB PostgreSQL版7.0版本增強了通用資料表運算式(Common Table Expression,簡稱CTE)功能,支援對CTE語句指定MATERIALIZED或NOT MATERIALIZED,可以更好地控制執行計畫,能夠有效提升SQL效能。
功能簡介
CTE可以在單個語句的執行範圍內定義臨時結果集,該結果集只在查詢期間有效。CTE可以自引用,也可在同一查詢中多次引用,實現了程式碼片段的重複利用。常見CTE語句格式如下:
WITH x1 AS
(SELECT a FROM t1),
x2 AS
(SELECT b FROM t1)
SELECT * FROM
x1 JOIN x2 ON x1.a = x2.b;CTE對查詢語句有如下兩種處理方法:
- MATERIALIZED:先在WITH子查詢內部進行計算,然後再匯總計算。
- NOT MATERIALIZED:將WITH子查詢強行拉取到父查詢中進行計算。
7.0版本以前,資料庫的最佳化器會自行決定採用上述的其中一種方法。7.0版本以後,您可以通過指定MATERIALIZED或NOT MATERIALIZED來幹預上述行為。樣本如下:
- 指定MATERIALIZED
EXPLAIN WITH x1 AS MATERIALIZED (SELECT * FROM t1) SELECT * FROM x1 WHERE a > 1;通過執行計畫可以看出,系統先計算了子查詢,再進行匯總計算。
QUERY PLAN --------------------------------------------------------------------------------------- Gather Motion 3:1 (slice1; segments:3) (cost=0.00..3085.25 rows=86100 width=8) -> Subquery Scan on x1 (cost=0.00..1937.25 rows=28700 width=8) Filter: (x1.a > 1) -> Shared Scan (share slice:id 1:0) (cost=321.00..355.50 rows=28700 width=8) -> Seq Scan on t1 (cost=0.00..321.00 rows=28700 width=8) Optimizer: Postgers query optimizer (6 rows) - 指定NOT MATERIALIZED
EXPLAIN WITH x1 AS NOT MATERIALIZED (SELECT * FROM t1) SELECT * FROM x1 WHERE a > 1;通過執行計畫樣本可以看出,系統直接將子查詢拉取到父查詢中進行計算。
QUERY PLAN ------------------------------------------------------------------------------ Gather Motion 3:1 (slice1; segments:3) (cost=0.00..775.42 rows=28700 width=8) -> Seq Scan on t1 (cost=0.00..392.75 rows=9567 width=8) Filter: (a > 1) Optimizer: Postgres query optimizer (4 rows)
樣本
- 樣本一:不使用CTE時的執行計畫
查看一個三表JOIN的執行計畫,通過以下執行計畫可以看出,預設JOIN順序為表t1先JOIN表t2後再JOIN表t3。

- 樣本二:使用CTE時指定MATERIALIZED
通過指定MATERIALIZED的方式改變JOIN順序,通過以下執行計畫可以看出,JOIN順序變為表t1先JOIN表t3後再JOIN表t2。

- 樣本三:使用CTE時指定MATERIALIZED
通過指定MATERIALIZED的方式改變JOIN順序,通過以下執行計畫可以看出,JOIN順序變為表t2先JOIN表t3後再JOIN表t1。
