2025年9月25日: PostgreSQL 18 釋出!
支援的版本: 當前 (18) / 17 / 16 / 15 / 14 / 13
開發版本: devel
不再支援的版本: 12

36.11. 函式最佳化資訊 #

預設情況下,一個函式只是一個數據庫系統對其行為知之甚少的“黑盒子”。然而,這意味著使用該函式的查詢的執行效率可能遠不如它們應有的效率。可以透過提供額外的知識來幫助最佳化器最佳化函式呼叫。

一些基本事實可以透過 CREATE FUNCTION 命令中提供的宣告性註解來提供。其中最重要的是函式的 易變性類別IMMUTABLESTABLEVOLATILE);在定義函式時,應始終謹慎正確地指定此項。如果希望在並行化查詢中使用該函式,還必須指定並行安全屬性(PARALLEL UNSAFEPARALLEL RESTRICTEDPARALLEL 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 請求型別。

提交更正

如果您在文件中發現任何不正確的內容,與您對特定功能的實際體驗不符,或者需要進一步澄清,請使用 此表單 報告文件問題。