要理解規則系統是如何工作的,有必要知道它何時被呼叫,以及它的輸入和結果是什麼。
規則系統位於解析器和規劃器之間。它接收解析器的輸出,一個查詢樹,以及使用者定義的重寫規則,這些重寫規則也是帶有額外資訊的查詢樹,並生成零個或多個查詢樹作為結果。因此,它的輸入和輸出總是解析器本身可以產生的,因此,它看到的任何東西基本上都可以表示為一個SQL語句。
那麼,什麼是查詢樹?它是一個內部表示,用於表示一個SQL語句,其中構建它的單個部分被單獨儲存。這些查詢樹可以在伺服器日誌中顯示,如果您設定了配置引數 debug_print_parse
、debug_print_rewritten
或 debug_print_plan
。規則動作也作為查詢樹儲存在系統目錄 pg_rewrite
中。它們不像日誌輸出那樣格式化,但包含完全相同的資訊。
讀取原始查詢樹需要一些經驗。但是,由於SQL查詢樹的表示形式足以理解規則系統,因此本章將不教授如何讀取它們。
在閱讀本章中的SQL查詢樹表示時,需要能夠識別語句在查詢樹結構中被分解成的部分。查詢樹的組成部分是
這是一個簡單的值,指示哪個命令(SELECT
、INSERT
、UPDATE
、DELETE
)生成了查詢樹。
範圍表是查詢中使用的關係的列表。在 SELECT
語句中,這些是 FROM
關鍵字後面的關係。
每個範圍表條目標識一個表或檢視,並說明它在查詢的其他部分中是如何被稱呼的。在查詢樹中,範圍表條目是透過編號而不是名稱來引用的,因此這裡即使有重複的名稱也不會像在 SELECT
SQL語句中那樣存在問題。當規則的範圍表被合併後,這種情況就可能發生。本章中的示例不會出現這種情況。
這是一個指向範圍表的索引,用於標識查詢結果要寫入的關係。
SELECT
查詢沒有結果關係。(SELECT INTO
的特殊情況幾乎與 CREATE TABLE
後跟 INSERT ... SELECT
相同,此處不單獨討論。)
對於 INSERT
、UPDATE
和 DELETE
命令,結果關係是更改要生效的表(或檢視!)。
目標列表是定義查詢結果的表示式列表。對於 SELECT
,這些表示式是構成查詢最終輸出的表示式。它們對應於 SELECT
和 FROM
關鍵字之間的表示式。(*
只是關係的所有列名的縮寫。它會被解析器展開成單獨的列,因此規則系統永遠不會看到它。)
DELETE
命令不需要普通的目標列表,因為它們不產生任何結果。相反,規劃器會在空目標列表中新增一個特殊的CTID條目,以便執行器能夠找到要刪除的行。(當結果關係是普通表時,會新增CTID。如果它是檢視,則如 第 39.2.4 節中所述,規則系統會新增一個整行變數。)
對於 INSERT
命令,目標列表描述了應該插入到結果關係中的新行。它由 VALUES
子句中的表示式或 INSERT ... SELECT
中的 SELECT
子句中的表示式組成。重寫過程的第一步會為任何未被原始命令賦值但有預設值的列新增目標列表條目。任何剩餘的列(既沒有指定值也沒有預設值)將被規劃器填充為常量 NULL 表示式。
對於 UPDATE
命令,目標列表描述了應該替換舊行的新行。在規則系統中,它只包含命令的 SET column = expression
部分中的表示式。規劃器將透過插入複製舊行值到新行的表示式來處理缺失的列。與 DELETE
一樣,也會新增一個CTID或整行變數,以便執行器能夠識別要更新的舊行。
目標列表中的每個條目都包含一個表示式,該表示式可以是常量值、指向範圍表中某個關係的列的變數、引數,或者由函式呼叫、常量、變數、運算子等組成的表示式樹。
查詢的限定條件是一個表示式,與目標列表條目中包含的表示式類似。此表示式的結果值是一個布林值,指示是否應執行最終結果行的操作(INSERT
、UPDATE
、DELETE
或 SELECT
)。它對應於 SELECT
的 WHERE
子句。SQL語句。
查詢的連線樹顯示了 FROM
子句的結構。對於像 SELECT ... FROM a, b, c
這樣的簡單查詢,連線樹只是 FROM
項的列表,因為我們可以按任何順序連線它們。但當使用 JOIN
表示式,特別是外連線時,我們必須按照連線顯示的順序進行連線。在這種情況下,連線樹顯示了 JOIN
表示式的結構。與特定 JOIN
子句相關聯的限制(來自 ON
或 USING
表示式)作為限定表示式儲存在那些連線樹節點上。將頂層 WHERE
表示式也作為限定表示式附加到頂層連線樹項上也可能很方便。因此,連線樹實際上代表了 SELECT
的 FROM
和 WHERE
子句。
查詢樹的其他部分,如 ORDER BY
子句,在此處不予關注。規則系統在應用規則時會替換其中的某些條目,但這與規則系統的基本原理關係不大。
如果您在文件中發現任何不正確、與您對特定功能的體驗不符或需要進一步澄清的內容,請使用 此表格 報告文件問題。