支援的版本:目前 (16) / 15 / 14 / 13 / 12
開發版本:devel
不支援的版本:11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2

70.3. 可擴充性 #

GIN 介面具有高度的抽象性,只要求存取方法實作人員實作所存取資料類型的語意。GIN 層本身會處理並行性、記錄以及搜尋樹狀結構。

要讓 GIN 存取方法運作,只需實作幾個使用者定義的方法,這些方法定義樹中金鑰的行為,以及金鑰、索引項目和可索引查詢之間的關係。簡而言之,GIN 結合了可擴充性與普遍性、程式碼重複使用和乾淨的介面。

對於 GIN 的運算子類別,必須提供兩種方法

Datum *extractValue(Datum itemValue, int32 *nkeys, bool **nullFlags)

傳回給定要編製索引的項目的金鑰陣列。傳回的金鑰數量必須儲存在 *nkeys 中。如果任何金鑰都可能是空值,也請 palloc 一個陣列,其中包含 *nkeys bool 欄位,將其位址儲存在 *nullFlags 中,並視需要設定這些空值標記。如果所有金鑰都不是空值,則可以將 *nullFlags 保留為 NULL(其初始值)。如果項目不包含任何金鑰,傳回值可以是 NULL

Datum *extractQuery(Datum query, int32 *nkeys, StrategyNumber n, bool **pmatch, Pointer **extra_data, bool **nullFlags, int32 *searchMode)

傳回給定要查詢的值的金鑰陣列;也就是說,query 是可索引運算子右手邊的值,而其左手邊是索引欄位。n 是運算子類別中運算子的策略編號(請參閱 第 38.16.2 節)。通常,extractQuery 需要諮詢 n 以判斷 query 的資料類型,以及它應該用來萃取金鑰值的方法。傳回的金鑰數量必須儲存在 *nkeys 中。如果任何金鑰都可能是空值,也請 palloc 一個陣列,其中包含 *nkeys bool 欄位,將其位址儲存在 *nullFlags 中,並視需要設定這些空值標記。如果所有金鑰都不是空值,則可以將 *nullFlags 保留為 NULL(其初始值)。如果 query 不包含任何金鑰,傳回值可以是 NULL

searchMode 是輸出引數,允許 extractQuery 指定有關如何執行搜尋的詳細資訊。如果 *searchMode 設定為 GIN_SEARCH_MODE_DEFAULT(這是呼叫之前初始化的值),則只會考慮與傳回金鑰之一相符的項目作為候選相符項。如果 *searchMode 設定為 GIN_SEARCH_MODE_INCLUDE_EMPTY,則除了包含至少一個相符金鑰的項目之外,不包含任何金鑰的項目也會被視為候選相符項。(例如,此模式對於實作子集運算子很有用。)如果 *searchMode 設定為 GIN_SEARCH_MODE_ALL,則索引中所有非空值項目都會被視為候選相符項,無論它們是否與任何傳回金鑰相符。(此模式比其他兩個選項慢得多,因為它需要掃描整個索引,但它可能是正確實作特殊情況所必需的。在大多數情況下需要此模式的運算子,可能不適合用於 GIN 運算子類別。)用於設定此模式的符號定義在 access/gin.h 中。

pmatch 是用於支援部分比對時使用的輸出引數。若要使用它,extractQuery 必須配置一個 *nkeys bool 的陣列,並將其位址儲存在 *pmatch。如果對應的鍵需要部分比對,則陣列的每個元素都應設定為 true,否則設定為 false。如果 *pmatch 設定為 NULL,則 GIN 會假設不需要部分比對。變數在呼叫之前會初始化為 NULL,因此不支援部分比對的運算子類別可以忽略這個引數。

extra_data 是輸出引數,允許 extractQuery 將額外資料傳遞給 consistentcomparePartial 方法。若要使用它,extractQuery 必須配置一個 *nkeys 指標的陣列,並將其位址儲存在 *extra_data,然後將它想要儲存的任何內容儲存在個別指標中。變數在呼叫之前會初始化為 NULL,因此不需要額外資料的運算子類別可以忽略這個引數。如果設定 *extra_data,則整個陣列會傳遞給 consistent 方法,而適當的元素會傳遞給 comparePartial 方法。

運算子類別還必須提供一個函數來檢查索引項目是否與查詢相符。它有兩種形式,一個布林 consistent 函數,以及一個三元 triConsistent 函數。triConsistent 包含兩者的功能,因此僅提供 triConsistent 就足夠了。但是,如果布林變體的計算成本顯著較低,則提供兩者會很有利。如果僅提供布林變體,則會停用一些在擷取所有鍵之前依賴於駁回索引項目的最佳化。

bool consistent(bool check[], StrategyNumber n, Datum query, int32 nkeys, Pointer extra_data[], bool *recheck, Datum queryKeys[], bool nullFlags[])

如果索引項目符合策略編號 n 的查詢運算子(或可能符合,如果傳回重新檢查指示),則傳回 true。此函式無法直接存取索引項目的值,因為 GIN 沒有明確儲存項目。相反地,可取得的資訊是關於從查詢中萃取的哪些金鑰值出現在給定的索引項目中。 check 陣列的長度為 nkeys,與先前由 extractQuery 為此 query 資料傳回的金鑰數量相同。如果索引項目包含對應的查詢金鑰,則 check 陣列的每個元素都為 true,亦即,如果 (check[i] == true),則 extractQuery 結果陣列的第 i 個金鑰存在於索引項目中。如果 consistent 方法需要諮詢原始 query 資料,則傳遞該資料,並且傳遞先前由 extractQuery 傳回的 queryKeys[]nullFlags[] 陣列。 extra_data 是由 extractQuery 傳回的額外資料陣列,如果沒有,則為 NULL

extractQueryqueryKeys[] 中傳回 null 金鑰時,如果索引項目包含 null 金鑰,則對應的 check[] 元素為 true;亦即,check[] 的語意類似於 IS NOT DISTINCT FROM。如果 consistent 函式需要區分一般值比對和 null 比對,則可以檢查對應的 nullFlags[] 元素。

成功時,如果堆組必須針對查詢運算子重新檢查,則應將 *recheck 設定為 true,如果索引測試精確,則設定為 false。亦即,傳回 false 值保證堆組與查詢不符;傳回 true 值且 *recheck 設定為 false 保證堆組與查詢相符;傳回 true 值且 *recheck 設定為 true 表示堆組可能與查詢相符,因此需要透過直接針對原始索引項目評估查詢運算子來擷取並重新檢查。

GinTernaryValue triConsistent(GinTernaryValue check[], StrategyNumber n, Datum query, int32 nkeys, Pointer extra_data[], Datum queryKeys[], bool nullFlags[])

triConsistentconsistent 類似,但 check 向量中不是布林值,而是每個鍵有三個可能的值:GIN_TRUEGIN_FALSEGIN_MAYBEGIN_FALSEGIN_TRUE 的意義與一般布林值相同,而 GIN_MAYBE 表示不知道該鍵是否存在。當存在 GIN_MAYBE 值時,只有在項目確實符合索引項目是否包含對應的查詢鍵時,函式才應傳回 GIN_TRUE。同樣地,只有在項目確實不符合時,函式才必須傳回 GIN_FALSE,無論是否包含 GIN_MAYBE 鍵。如果結果取決於 GIN_MAYBE 項目,亦即無法根據已知的查詢鍵確認或反駁配對,則函式必須傳回 GIN_MAYBE

check 向量中沒有 GIN_MAYBE 值時,GIN_MAYBE 傳回值等於在布林 consistent 函式中設定 recheck 旗標。

此外,GIN 必須有方法來排序儲存在索引中的鍵值。運算子類別可透過指定比較方法來定義排序順序

int compare(Datum a, Datum b)

比較兩個鍵(不是已編製索引的項目!)並傳回小於零、等於零或大於零的整數,表示第一個鍵小於、等於或大於第二個鍵。從不將 Null 鍵傳遞給此函式。

或者,如果運算子類別未提供 compare 方法,GIN 會查詢索引鍵資料類型的預設 btree 運算子類別,並使用其比較函式。建議在專門用於單一資料類型的 GIN 運算子類別中指定比較函式,因為查詢 btree 運算子類別會花費一些週期。然而,多型 GIN 運算子類別(例如 array_ops)通常無法指定單一比較函式。

GIN 的運算子類別可以選擇提供下列方法

int comparePartial(Datum partial_key, Datum key, StrategyNumber n, Pointer extra_data)

將部分配對查詢鍵與索引鍵進行比較。傳回一個整數,其符號表示結果:小於零表示索引鍵與查詢不匹配,但索引掃描應繼續;等於零表示索引鍵與查詢匹配;大於零表示索引掃描應停止,因為不可能再有更多配對。提供產生部分配對查詢的運算子的策略編號 n,以防需要其語意來判斷何時結束掃描。另外,extra_dataextractQuery 建立的額外資料陣列的對應元素,或在沒有時為 NULL。從不將 Null 鍵傳遞給此函式。

void options(local_relopts *relopts)

定義一組使用者可見的參數,用於控制運算子類別的行為。

options 函式傳遞給 local_relopts 結構的指標,需要使用一組運算子類別特定選項來填寫。可以使用 PG_HAS_OPCLASS_OPTIONS()PG_GET_OPCLASS_OPTIONS() 巨集從其他支援函式存取選項。

由於索引值的關鍵提取和 GIN 中關鍵的表示是彈性的,因此它們可能取決於使用者指定的參數。

為了支援 部分比對 查詢,運算子類別必須提供 comparePartial 方法,並且其 extractQuery 方法必須在遇到部分比對查詢時設定 pmatch 參數。有關詳細資訊,請參閱 第 70.4.2 節

上述各種 Datum 值的實際資料類型會根據運算子類別而有所不同。傳遞給 extractValue 的項目值始終是運算子類別的輸入類型,並且所有關鍵值都必須是類別的 STORAGE 類型。extractQueryconsistenttriConsistent 傳遞的 query 參數類型是策略編號識別的類別成員運算子的右手輸入類型。這不一定是索引類型,只要可以從中提取正確類型的關鍵值即可。但是,建議這些三個支援函式的 SQL 宣告使用 opclass 的索引資料類型作為 query 參數,即使實際類型可能根據運算子而有所不同。

提交更正

如果您在文件中看到任何不正確、與您對特定功能的體驗不符或需要進一步說明的內容,請使用 此表單 回報文件問題。