PostgreSQL 可擴(kuò)展性

2021-09-15 11:46 更新

GIN接口有一個(gè)高層次的抽象,要求訪問方法實(shí)現(xiàn)者只需要實(shí)現(xiàn)數(shù)據(jù)類型被訪問的語義。GIN層本身會(huì)操心并發(fā)、日志和搜索樹結(jié)構(gòu)的事情。

要讓一個(gè)GIN訪問方法工作起來所要做的全部事情就是實(shí)現(xiàn)一些用戶定義的方法,它們定義了樹中鍵的行為以及鍵、被索引項(xiàng)以及可索引查詢之間的關(guān)系。簡而言之,GIN的可擴(kuò)展性結(jié)合了通用性、代碼重用和一個(gè)干凈的接口。

一個(gè)用于GIN的操作符類必須提供的兩種方法是:

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

給定一個(gè)要被索引的項(xiàng),返回一個(gè) palloc 過的鍵的數(shù)組。被返回的鍵的數(shù)量必須被存儲(chǔ)在*nkeys中。如果鍵中的任意一個(gè)可能為空,還要 palloc 一個(gè)*nkeys 個(gè)bool域的數(shù)組,將它的地址存儲(chǔ)在*nullFlags中,并且根據(jù)需要設(shè)置這些空值標(biāo)志。如果所有的鍵都非空, *nullFlags可以被留成NULL(其初始值)。如果該項(xiàng)不包含鍵,返回值可以為NULL

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

給定一個(gè)要被查詢的值,返回一個(gè) palloc 過的鍵的數(shù)組。即query是一個(gè)可索引操作符(左手邊是被索引列)的右手邊的值。n是操作符類中操作符的策略號(hào)(見第 37.16.2 節(jié))。通常, extractQuery將需要參考n來判斷query的數(shù)據(jù)類型以及它應(yīng)該用什么方法來抽取鍵值。被返回的鍵的數(shù)量必須被存儲(chǔ)在*nkeys中。如果鍵中的任意一個(gè)可能為空,還要 palloc 一個(gè)*nkeys 個(gè)bool域的數(shù)組,將它的地址存儲(chǔ)在 *nullFlags中,并且根據(jù)需要設(shè)置這些空值標(biāo)志。如果所有的鍵都非空,*nullFlags可以被留成NULL(其初始值)。如果該項(xiàng)不包含鍵,返回值可以為NULL。

searchMode是一個(gè)輸出參數(shù),它允許extractQuery指定有關(guān)搜索如何被完成的細(xì)節(jié)。如果*searchMode被設(shè)置為GIN_SEARCH_MODE_DEFAULT(這是在被調(diào)用之前它被初始化的值),只有那些匹配至少一個(gè)被返回鍵的項(xiàng)才會(huì)被考慮作為候選匹配。如果 *searchMode被設(shè)置為GIN_SEARCH_MODE_INCLUDE_EMPTY,那么除了至少包含一個(gè)匹配鍵的項(xiàng)之外,根本不包含鍵的項(xiàng)也被考慮作為候選匹配(例如,這種模式對(duì)于實(shí)現(xiàn)“是...的子集”操作符有用)。如果*searchMode被設(shè)置為GIN_SEARCH_MODE_ALL,那么索引中所有非空項(xiàng)都被考慮作為候選匹配,不管它們是否匹配被返回的鍵(這種模式比其他兩種選擇要慢很多,但是它對(duì)于正確實(shí)現(xiàn)極端情況可能是必要的。需要這種模式的操作符在大部分情況下可能并不是一個(gè) GIN 操作符類的好選擇)。用于設(shè)置這個(gè)模式的符號(hào)被定義在access/gin.h中。

pmatch是一個(gè)輸出參數(shù),它用于在部分匹配匹配被支持時(shí)使用。要用它,extractQuery必須分配一個(gè)*nkeys個(gè)布爾值的數(shù)組,并且把它的地址存儲(chǔ)在*pmatch中。如果一個(gè)鍵要求部分匹配,該數(shù)組的對(duì)應(yīng)元素應(yīng)該被設(shè)置為 TRUE,否則設(shè)置為 FALSE。如果 *pmatch被設(shè)置為NULL,則 GIN 假定不需要部分匹配。在調(diào)用前,該變量被初始化為NULL,這樣這個(gè)參數(shù)可以簡單地被不支持部分匹配的操作符類忽略。

extra_data是一個(gè)輸出參數(shù),它允許extractQuery傳遞額外數(shù)據(jù)給consistentcomparePartial方法。要用它,extractQuery必須分配一個(gè)*nkeys個(gè)指針的數(shù)組,并且把它的地址存儲(chǔ)在 *extra_data中,然后把任何它想存儲(chǔ)的東西存到單個(gè)指針中。在調(diào)用前該變量被初始化為NULL,這樣這個(gè)參數(shù)可以簡單地被不需要額外數(shù)據(jù)的操作符類忽略。如果*extra_data被設(shè)置,整個(gè)數(shù)組被傳遞給consistent方法,并且適當(dāng)?shù)脑貢?huì)被傳遞給comparePartial方法。

一個(gè)操作符類必須提供一個(gè)函數(shù)檢查一個(gè)被索引的項(xiàng)是否匹配查詢。有兩種形式, 一個(gè)布爾函數(shù)consistent,以及一個(gè)三元函數(shù)triConsistent。 triConsistent覆蓋了兩者的功能,因此提供triConsistent一個(gè)足矣。但是, 如果布爾變體的計(jì)算代價(jià)要更低,兩者都提供就會(huì)有好處。如果只提供布爾變體, 一些基于在取得所有鍵之前拒絕索引項(xiàng)的優(yōu)化將會(huì)被禁用。

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

如果一個(gè)被索引項(xiàng)滿足(如果重新檢查指示被返回,則表示可能滿足)有策略號(hào)n的查詢操作符,則返回 TRUE。這個(gè)函數(shù)并沒有直接訪問被索引項(xiàng)的值,因?yàn)?acronym class="acronym">GIN沒有顯式存儲(chǔ)項(xiàng)??捎玫氖顷P(guān)于哪些從查詢抽取出的鍵值出現(xiàn)在一個(gè)給定被索引項(xiàng)中的知識(shí)。check數(shù)組的長度是nkeys,它和前面由 extractQuery為這個(gè)查詢數(shù)據(jù)返回的鍵的數(shù)目相同。 如果被索引項(xiàng)包含一個(gè)查詢鍵,那么check數(shù)組的對(duì)應(yīng)元素為 TRUE,即如果 (check[i] == TRUE) ,則extractQuery結(jié)果數(shù)組的第 i 個(gè)鍵存在于被索引項(xiàng)中。在consistent方法需要參考原始 query數(shù)據(jù)的情況中,它會(huì)被傳遞進(jìn)來,前面由extractQuery返回的queryKeys[]nullFlags[]數(shù)組也一樣。extra_data是由extractQuery返回的額外數(shù)據(jù)數(shù)組,如果沒有額外數(shù)據(jù)則為 NULL。

當(dāng)extractQueryqueryKeys[]中返回一個(gè)空值鍵時(shí),如果被索引項(xiàng)包含一個(gè)空值鍵則對(duì)應(yīng)的check[]元素為 TRUE。即,check[]的語義類似IS NOT DISTINCT FROM。如果 consistent函數(shù)需要說出一個(gè)常規(guī)值匹配和一個(gè)空值匹配之間的區(qū)別,它可以檢查對(duì)應(yīng)的nullFlags[]元素。

在成功時(shí),如果堆元組需要根據(jù)查詢操作符被重新檢查,則*recheck應(yīng)該被設(shè)置為 TRUE,或者如果索引測試是準(zhǔn)確的則設(shè)置為 FALSE。即,一個(gè) FALSE 返回值保證堆元組不匹配查詢;一個(gè) TRUE 返回值以及設(shè)置為 FALSE 的*recheck保證堆元組匹配查詢;并且一個(gè) TRUE 返回值和設(shè)置為 TRUE 的*recheck表示堆元組可能匹配查詢,因此它需要被取出并且通過在原始的被索引項(xiàng)上計(jì)算查詢操作符來重新檢查。

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

triConsistent類似于consistent, 但和check[]中的布爾值不同,對(duì)每個(gè)鍵有三種可能值: GIN_TRUE、GIN_FALSEGIN_MAYBE。 GIN_FALSEGIN_TRUE具有和常規(guī)布爾值相同的含義, 而GIN_MAYBE意味著鍵的存在未知。當(dāng)GIN_MAYBE值出現(xiàn)時(shí), 如果項(xiàng)必定匹配(不管該索引項(xiàng)是否包含對(duì)應(yīng)的查詢鍵),該函數(shù)應(yīng)該只返回GIN_TRUE。 同樣地,如果項(xiàng)必定不匹配(不管它是否包含 GIN_MAYBE), 該函數(shù)必須只返回GIN_FALSE。 如果結(jié)果依賴于GIN_MAYBE項(xiàng),即無法根據(jù)已知查詢鍵確認(rèn)或拒絕匹配, 該函數(shù)必須返回GIN_MAYBE。

當(dāng)在check向量中沒有GIN_MAYBE值時(shí), GIN_MAYBE返回值等效于在布爾函數(shù)consistent中設(shè)置 recheck標(biāo)志等效。

此外,GIN必須有方法能排序存儲(chǔ)在索引中的鍵值。操作符類可以通過指定一種比較方法來定義排序順序:

int compare(Datum a, Datum b)

比較兩個(gè)鍵(不是被索引項(xiàng)!)并且返回一個(gè)整數(shù),該整數(shù)為小于零、等于零或者大于零分別表示第一個(gè)鍵小于、等于或者大于第二個(gè)鍵??罩垫I絕不會(huì)被傳遞給這個(gè)函數(shù)。

或者,如果操作符類不提供compare方法,GIN將查看索引鍵數(shù)據(jù)類型的默認(rèn)btree操作符類,并且使用它的比較函數(shù)。推薦為只用于一種數(shù)據(jù)類型的GIN操作符類指定這個(gè)比較函數(shù),因?yàn)椴檎襜tree操作符類需要消耗一些周期。不過,多態(tài)的GIN操作符類(例如array_ops)通常無法指定單一的比較函數(shù)。

一個(gè)用于GIN的操作符類可以選擇性的提供下列方法:

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

比較一個(gè)部分匹配鍵和一個(gè)索引鍵。返回一個(gè)整數(shù),其符號(hào)指示結(jié)果:小于零表示索引鍵不匹配查詢,但是索引掃描應(yīng)該繼續(xù);零表示索引鍵匹配查詢;大于零表示索引掃描應(yīng)該停止,因?yàn)闆]有更多可能的匹配。產(chǎn)生該部分匹配查詢的操作符的策略號(hào)n將被提供,可以通過其語義決定什么時(shí)候結(jié)束掃描。還有,extra_data是由extractQuery產(chǎn)生的額外數(shù)據(jù)數(shù)組中的對(duì)應(yīng)元素,如果沒有則為 NULL。空值不會(huì)被傳遞給這個(gè)函數(shù)。

void options(local_relopts *relopts)

定義一組用戶可見的參數(shù)以控制操作符類的行為。

options 函數(shù)傳遞一個(gè)指針到一個(gè)local_relopts結(jié)構(gòu),該結(jié)構(gòu)需要用一組特定的操作符類的選項(xiàng)來填充。 該選項(xiàng)可以使用PG_HAS_OPCLASS_OPTIONS()PG_GET_OPCLASS_OPTIONS()宏,從其他支持的函數(shù)進(jìn)行訪問。

由于索引值的鍵提取和鍵在GIN中的表示都是靈活的,它們可能取決于用戶指定的參數(shù)。

要支持部分匹配查詢,一個(gè)操作符類必須提供comparePartial方法,并且它的extractQuery方法必須在遇到一個(gè)部分匹配查詢時(shí)設(shè)置pmatch參數(shù)。詳見第 66.4.2 節(jié)。

上面提到的多個(gè)Datum值的實(shí)際數(shù)據(jù)類型隨著操作符類而變化。 被傳遞給extractValue的項(xiàng)值總是操作符類的輸入類型, 并且所有的鍵值必須是類的STORAGE類型。被傳遞給extractQuery、 consistenttriConsistentquery 參數(shù)是由該策略號(hào)標(biāo)識(shí)的類成員操作符的右手邊輸入類型。 這不需要和被索引類型相同,只要正確類型的鍵值能從其中被抽取出來。不過, 推薦這三個(gè)支持函數(shù)的 SQL 聲明對(duì)query參數(shù)使用操作符類的被 索引數(shù)據(jù)類型,即便實(shí)際類型可能是某種其他依賴于操作符的東西時(shí)也應(yīng)如此。


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

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)