PostgreSQL查詢優化器--邏輯查詢優化--檢視優化(一)
8.1.1 檢視重寫
PostgreSQL有一個模組,稱為規則模組,用以處理規則。規則系統把查詢修改為需要考慮規則的形式,然後把修改過的查詢傳遞給查詢優化器執行。檢視被作為規則的子部分,在此被處理。所以,PostgreSQL通過規則模組(pg_rewrite_query函式)支援邏輯查詢優化的檢視重寫,也就是把檢視用檢視的定義替代,檢視定義在SQL中相當於子查詢。PostgreSQL統一對子查詢進行優化。
PostgreSQL支援簡單檢視重寫和複雜檢視的重寫,支援對帶有簡單檢視重寫後的SQL語句進行優化,但
支援對帶有複雜檢視重寫後的SQL語句做優化。下面我們通過四組針對檢視的查詢例項進行對比,以幫助讀者掌握PostgreSQL
首先讓我們做一些準備性的工作。
建立表,命令如下:
CREATE TABLE t1 (a1 int UNIQUE, b1 int);
CREATE TABLE t2 (a2 int UNIQUE, b2 int);
CREATE TABLE t3 (a3 int UNIQUE, b3 int);
建立簡單檢視,命令如下:
CREATE VIEW v_t_1_2 AS SELECT * FROM t1, t2;
建立複雜檢視,命令如下:
CREATE VIEW v_t_gd_1_2 AS SELECT DISTINCT t1.b1, t2.b2 FROM t1, t2 GROUP BY t1.b1, t2.b2;
示例1 在簡單檢視上執行連線操作。
直接用檢視和表做連線操作,查詢執行計劃如下:
test=# EXPLAIN SELECT * FROM t1, v_t_1_2 WHERE t1.a1<20; QUERY PLAN ------------------------------------------------------------------ NestedLoop(cost=0.00..250291.15 rows=20000000 width=24) ->NestedLoop(cost=0.00..273.65 rows
從查詢執行計劃看,檢視v_t_1_2的名稱沒有出現,而且檢視中的t1表和原先的t1表先進行連線,t2表被最後連線,這說明檢視被重寫,重寫後的檢視定義部分作為子查詢被上拉處理,上拉後的查詢語句已經只是三個表(t1、t1、t2)之間進行連線了。
另外,對於條件“a1 < 20”,只在一個t1表被索引掃描時被使用,沒有能在t1表被順序掃描時使用,且t1表被掃描2次,不能有效利用物化的結果,PostgreSQL對於這種情況有待改進。
等價於上一條檢視的子查詢,沒有檢視存在,查詢執行計劃如下:
test=# EXPLAIN SELECT * FROM t1, (SELECT * FROM t1, t2) t12 WHERE t1.a1<20; QUERY PLAN ------------------------------------------------------------------ NestedLoop(cost=0.00..250291.15 rows=20000000 width=24) ->NestedLoop(cost=0.00..273.65 rows=20000 width=16) ->SeqScan on t1 (cost=0.00..15.00 rows=1000 width=8) ->Materialize(cost=0.00..8.70 rows=20 width=8) ->IndexScanusing t1_a1_key on t1 (cost=0.00..8.60 rows=20 width=8) IndexCond:(a1 <20) ->Materialize(cost=0.00..20.00 rows=1000 width=8) ->SeqScan on t2 (cost=0.00..15.00 rows=1000 width=8) (8行記錄)
從查詢執行計劃看,本條子查詢語句的查詢執行計劃與上一條基於檢視的查詢語句的查詢執行計劃完全相同,這表明二者是完全等價的,PostgreSQL支援對簡單檢視的重寫。