預設情況下,函式只是一個資料庫系統對其行為知之甚少的「黑盒子」。然而,這意味著使用該函式的查詢可能執行的效率遠低於應有的效率。可以提供額外的知識,以幫助規劃器最佳化函式呼叫。
一些基本事實可以透過 CREATE FUNCTION
命令中提供的宣告式註解來提供。其中最重要的是函式的變動性類別(IMMUTABLE
、STABLE
或 VOLATILE
);在定義函式時,應始終小心正確指定此項。如果希望在平行化查詢中使用該函式,也必須指定平行安全屬性(PARALLEL UNSAFE
、PARALLEL RESTRICTED
或 PARALLEL SAFE
)。指定函式的估計執行成本,以及/或設定傳回函式估計傳回的列數也可能很有用。但是,宣告式指定這些兩個事實的方式僅允許指定一個常數值,這通常是不夠的。
也可以將規劃器支援函式附加到 SQL 可呼叫函式(稱為其目標函式),從而提供關於目標函式的知識,這些知識太過複雜,無法以宣告方式表示。規劃器支援函式必須以 C 語言編寫(儘管其目標函式可能不是),因此這是一項進階功能,相對較少人會使用。
規劃器支援函式必須具有 SQL 簽章
supportfn(internal) returns internal
透過在建立目標函式時指定 SUPPORT
子句,將其附加到目標函式。
規劃器支援函式的 API 詳細資訊可以在 PostgreSQL 原始碼的 src/include/nodes/supportnodes.h
檔案中找到。在此,我們僅概述規劃器支援函式可以做什麼。支援函式的可能請求集是可擴充的,因此在未來的版本中可能會實現更多功能。
某些函式呼叫可以在規劃期間基於函式特定的屬性進行簡化。例如,int4mul(n, 1)
可以簡化為 n
。這種型別的轉換可以由規劃器支援函式來執行,方法是讓它實作 SupportRequestSimplify
請求型別。將針對在查詢剖析樹中找到的其目標函式的每個實例呼叫支援函式。如果它發現特定的呼叫可以簡化為其他形式,它可以建構並傳回代表該運算式的剖析樹。這也將自動適用於基於該函式的運算子 — 在剛才給出的範例中,n * 1
也將簡化為 n
。(但請注意,這只是一個範例;標準 PostgreSQL 實際上並未執行此特定最佳化。)我們不保證 PostgreSQL 永遠不會在支援函式可以簡化的情況下呼叫目標函式。確保簡化的運算式與目標函式的實際執行之間具有嚴格的等效性。
對於傳回 boolean
的目標函式,通常很有用的是估計使用該函式的 WHERE
子句將選取的列的分數。這可以由實作 SupportRequestSelectivity
請求型別的支援函式來完成。
如果目標函式的執行時間高度取決於其輸入,則為其提供非恆定成本估計可能很有用。這可以由實作 SupportRequestCost
請求型別的支援函式來完成。
對於傳回集合的目標函式,提供將傳回的列數的非恆定估計通常很有用。這可以由實作 SupportRequestRows
請求型別的支援函式來完成。
對於傳回 boolean
的目標函式,可以將 WHERE
中出現的函式呼叫轉換為可索引的運算子子句。轉換後的子句可能與函式的條件完全等效,或者它們可能稍微弱一些(也就是說,它們可能接受函式條件不接受的一些值)。在後一種情況下,索引條件被認為是有損的;它仍然可以用於掃描索引,但是必須針對索引傳回的每一列執行函式呼叫,以查看它是否真的通過了 WHERE
條件。若要建立此類條件,支援函式必須實作 SupportRequestIndexCondition
請求型別。
如果您在文件中發現任何不正確、與特定功能不符或需要進一步澄清的地方,請使用此表單報告文件問題。