PostgreSQL 查詢樹

2021-09-03 16:30 更新

要了解規(guī)則系統(tǒng)是如何工作的,必須要知道它什么時(shí)候被調(diào)用以及它的輸入和結(jié)果是什么。

規(guī)則系統(tǒng)位于解析器和規(guī)劃器之間。它采用解析器的輸出(即一個(gè)查詢樹)和用戶定義的重寫規(guī)則(也是查詢樹,不過帶有一些額外信息),并且常見零個(gè)或者更多個(gè)查詢樹作為結(jié)果。因此它的輸入和輸出總是那些規(guī)劃器自身就能產(chǎn)生的東西,并且因此它看到的任何東西都可以被表示成一個(gè)SQL語句。

那么什么是一個(gè)查詢樹?它是一個(gè)SQL語句的一種內(nèi)部表示,其中用于創(chuàng)建它的每一個(gè)單獨(dú)的部分都被獨(dú)立存儲。如果你設(shè)置了配置參數(shù)debug_print_parse、debug_print_rewrittendebug_print_plan,這些查詢樹可以被顯示在服務(wù)器日志中。規(guī)則動作也被做為查詢樹存儲在系統(tǒng)目錄 pg_rewrite中。它們沒有被格式化為日志輸出的形式,但是它們包含完全相同的信息。

閱讀一棵未加工的查詢樹需要要一些經(jīng)驗(yàn)。但是由于查詢樹的SQL表示形式足以用來理解規(guī)則系統(tǒng),本章將不會教授如何閱讀查詢樹。

在閱讀本章中查詢樹的SQL表現(xiàn)形式時(shí),讀者需要能夠知道語句被分解成了哪些部分并且能在查詢樹結(jié)構(gòu)中標(biāo)識它們。一棵查詢樹的部分有:

命令類型

這是一個(gè)簡單的值來說明是哪一種命令(SELECTINSERT、UPDATE、DELETE)產(chǎn)生了該查詢樹。

范圍表

范圍表是被使用在該查詢中的關(guān)系的列表。在一個(gè)SELECT語句中,范圍表是在關(guān)鍵詞FROM后面給出的關(guān)系。

每一個(gè)范圍表項(xiàng)標(biāo)識一個(gè)表或視圖,并且說明在該查詢的其他部分要以哪個(gè)名稱調(diào)用它。在查詢樹中,范圍表項(xiàng)被使用編號而不是名稱來引用,因此在一個(gè)SQL語句中出現(xiàn)重復(fù)的名字也沒有關(guān)系。在規(guī)則的范圍表被合并以后可能會發(fā)生這種情況。本章中的例子將不會有這種情況。

結(jié)果關(guān)系

這是一個(gè)指向范圍表的索引,它標(biāo)識了該查詢的結(jié)果應(yīng)該去哪個(gè)關(guān)系。

SELECT查詢沒有結(jié)果關(guān)系(特殊情況SELECT INTO幾乎等于CREATE TABLE后面跟上INSERT ... SELECT,并且不在這里單獨(dú)討論)。

對于INSERT、UPDATEDELETE命令,結(jié)果關(guān)系是修改要進(jìn)行的表(或視圖!)。

目標(biāo)列表

目標(biāo)列表是一個(gè)表達(dá)式的列表,它定義了查詢的結(jié)果。在一個(gè)SELECT的情況下,這些表達(dá)式會構(gòu)建出該查詢最終的輸出。它們對應(yīng)于關(guān)鍵字SELECTFROM之間的表達(dá)式(*是一個(gè)關(guān)系所有列名的縮寫。解析器會把它擴(kuò)展成獨(dú)立的列,因此規(guī)則系統(tǒng)永遠(yuǎn)見不到它)。

DELETE命令不需要一個(gè)目標(biāo)列表,因?yàn)樗鼈儾划a(chǎn)生任何結(jié)果。相反,規(guī)劃器會向空的目標(biāo)列表中加入一個(gè)特殊的CTID項(xiàng)來允許執(zhí)行器找到要被刪除的行(當(dāng)結(jié)果關(guān)系是一個(gè)普通表時(shí)才加入CTID。如果結(jié)果關(guān)系是一個(gè)視圖,則會被規(guī)則系統(tǒng)加入一個(gè)整行變量,如第 40.2.4 節(jié)所述)。

對于INSERT命令,目標(biāo)列表描述了將要進(jìn)入到結(jié)果關(guān)系中的新行。它由VALUES子句中的表達(dá)式或來自INSERT ... SELECTSELECT子句的表達(dá)式構(gòu)成。重寫處理的第一步會為那些沒有被原始命令賦值但有默認(rèn)值的列增加目標(biāo)列項(xiàng)。任何剩余的列(既沒有給定值也沒有默認(rèn)值)將被規(guī)劃器用一個(gè)常量空值表達(dá)式填充。

對于UPDATE命令,目標(biāo)列表描述要替換舊行的新行。在規(guī)則系統(tǒng)中,它只包含來自命令的SET column = expression部分的表達(dá)式。規(guī)劃器將處理缺失的列,做法是為它們插入表達(dá)式,這種表達(dá)式會把舊行的值復(fù)制到新行。正如DELETE一樣,會增加一個(gè)CTID或整行變量,這樣執(zhí)行器能夠標(biāo)識要被更新的舊行。

目標(biāo)列表中的每一個(gè)項(xiàng)所包含的表達(dá)式可以是一個(gè)常量值、一個(gè)指向范圍表中關(guān)系的列的變量、一個(gè)參數(shù)或一個(gè)由函數(shù)調(diào)用、常量、變量、操作符等構(gòu)成的表達(dá)式樹。

條件

查詢的條件是一個(gè)表達(dá)式,它很像包含在目標(biāo)列表項(xiàng)中的表達(dá)式。這個(gè)表達(dá)式的結(jié)果值是一個(gè)布爾值,它說明對最終結(jié)果行的操作(INSERT、UPDATEDELETESELECT)是否應(yīng)該被執(zhí)行。它對應(yīng)于一個(gè)SQL語句的 WHERE子句。

連接樹

查詢的連接樹展示了FROM子句的結(jié)構(gòu)。對于一個(gè)SELECT ... FROM a, b, c這樣的簡單查詢,連接樹就是FROM項(xiàng)的一個(gè)列表,因?yàn)槲覀儽辉试S以任何順序連接它們。但是當(dāng)JOIN表達(dá)式(特別是外連接)被使用時(shí),我們必須按照連接顯示的順序來連接。在這種情況下,連接樹展示了 JOIN表達(dá)式的結(jié)構(gòu)。與特定JOIN子句(來自ONUSING)相關(guān)的限制被存儲為附加到那些連接樹節(jié)點(diǎn)的條件表達(dá)式。我們發(fā)現(xiàn)把頂層WHERE表達(dá)式存儲為附加到頂層連接樹項(xiàng)的一個(gè)條件也很方便。這樣實(shí)際上連接樹表達(dá)了一個(gè)SELECTFROMWHERE子句。

其他

查詢樹的其他部分(如ORDER BY子句)在這里并不受到關(guān)注。規(guī)則系統(tǒng)在應(yīng)用規(guī)則時(shí)會替換這里的某些項(xiàng),但是這些與規(guī)則系統(tǒng)的基礎(chǔ)沒有什么關(guān)系。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號