W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
索引訪問(wèn)方法必須在IndexAmRoutine
中提供的索引構(gòu)造和維護(hù)函數(shù)有:
IndexBuildResult *
ambuild (Relation heapRelation,
Relation indexRelation,
IndexInfo *indexInfo);
創(chuàng)建一個(gè)新索引。索引關(guān)系已經(jīng)被物理創(chuàng)建,但是是空的。必須用索引訪問(wèn)方法要求的固定數(shù)據(jù)填充它,外加所有已經(jīng)在表里的行的項(xiàng)。通常,ambuild
函數(shù)會(huì)調(diào)用table_index_build_scan()
來(lái)掃描表以獲取現(xiàn)有元組并計(jì)算需要被插入到索引的鍵。該函數(shù)必須返回一個(gè)已分配內(nèi)存的結(jié)構(gòu),其中包含關(guān)于新索引的統(tǒng)計(jì)信息。
void
ambuildempty (Relation indexRelation);
構(gòu)建一個(gè)空索引,并且把它寫入到給定關(guān)系的初始化分叉中( INIT_FORKNUM
)。只會(huì)為不做日志的索引調(diào)用這個(gè)方法,被寫入到 初始化分叉的空索引在每次服務(wù)器啟動(dòng)時(shí)將被復(fù)制到主關(guān)系分叉中。
bool
aminsert (Relation indexRelation,
Datum *values,
bool *isnull,
ItemPointer heap_tid,
Relation heapRelation,
IndexUniqueCheck checkUnique,
IndexInfo *indexInfo);
向現(xiàn)有索引插入一個(gè)新元組。values
和isnull
數(shù)組給出需要被索引的鍵值,而heap_tid
是要被索引的 TID。 如果該訪問(wèn)方法支持唯一索引(它的amcanunique
標(biāo)志為真),那么checkUnique
指示要執(zhí)行的唯一性檢查類型。這根據(jù)唯一約束是否為可推遲的而變化,詳見(jiàn)
第 61.5 節(jié)。通常在執(zhí)行唯一性檢查時(shí)訪問(wèn)方法僅需要heapRelation
參數(shù)(因?yàn)槟菚r(shí)它將不得不到堆中驗(yàn)證元組的存活性)。
該函數(shù)的布爾結(jié)果值僅僅在checkUnique
為UNIQUE_CHECK_PARTIAL
時(shí)才有意義。這種情況下一個(gè)“真”結(jié)果意味著這個(gè)新項(xiàng)是已知唯一的,反之“假”結(jié)果意味著它可能不 是唯一的(并且一個(gè)延遲的唯一性校驗(yàn)必須是預(yù)定的)。對(duì)于其他情況,建議使用一個(gè)常量“假”結(jié)果。
有些索引可能不會(huì)索引所有元組。如果元組不被索引,aminsert
應(yīng)該僅返回而什么都不做。
如果索引AM希望在SQL語(yǔ)句中連續(xù)的索引插入之間緩沖數(shù)據(jù),它可以在indexInfo->ii_Context
中分配空間并且在indexInfo->ii_AmCache
(初始為NULL)中存放一個(gè)指向該數(shù)據(jù)的指針。
IndexBulkDeleteResult *
ambulkdelete (IndexVacuumInfo *info,
IndexBulkDeleteResult *stats,
IndexBulkDeleteCallback callback,
void *callback_state);
從索引中刪除元組。這是一個(gè)“批量刪除”操作,它的意圖是通過(guò)掃描整個(gè)索引并檢查每個(gè)項(xiàng)看它是否需要被刪除。被傳遞進(jìn)來(lái)的callback
函數(shù)必須被調(diào)用(調(diào)用風(fēng)格是:callback(
)來(lái)判斷任何其引用的 TID 標(biāo)識(shí)的索引項(xiàng)是否需要?jiǎng)h除。必須返回 NULL 或者是一個(gè) palloc 過(guò)的、 包含刪除操作效果的統(tǒng)計(jì)信息的結(jié)構(gòu)。如果不需要向TID
, callback_state) returns boolamvacuumcleanup
傳遞信息,返回 NULL 也是 OK 的。
由于maintenance_work_mem
被限制,在刪除多行的時(shí)候ambulkdelete
可能需要被調(diào)用多次。stats
參數(shù)是對(duì)這個(gè)索引上一次調(diào)用的結(jié)果(在一個(gè)VACUUM
操作中第一次調(diào)用時(shí)是 NULL)。這將允許 AM 在整個(gè)操作過(guò)程中積累統(tǒng)計(jì)信息。典型的,如果被傳遞的
stats
非空,ambulkdelete
將會(huì)修改并返回相同的結(jié)構(gòu)。
IndexBulkDeleteResult *
amvacuumcleanup (IndexVacuumInfo *info,
IndexBulkDeleteResult *stats);
在一個(gè)VACUUM
操作(零個(gè)或更多次ambulkdelete
調(diào)用)后清空。雖然不必做任何返回索引統(tǒng)計(jì)信息之外的事情,但是它可能執(zhí)行批量清理,例如回收空索引頁(yè)面。stats
是最后一次ambulkdelete
調(diào)用返回的東西或者 NULL(如果沒(méi)有元組需要?jiǎng)h除而未調(diào)用
ambulkdelete
)。如果結(jié)果不是 NULL,那么它必須是一個(gè)已經(jīng)被 palloc 的結(jié)構(gòu)。它包含的統(tǒng)計(jì)信息將用于更新pg_class
并且由VACUUM
報(bào) 告(如果給出了VERBOSE
)。如果索引在VACUUM
操作期間根本沒(méi)有改變,那么返回
NULL 也是可以的,否則必須返回正確的統(tǒng)計(jì)信息。
從PostgreSQL 8.4 開(kāi)始,amvacuumcleanup
將也會(huì)在一個(gè)ANALYZE
操作結(jié)束時(shí)被調(diào)用。這種情況中stats
總是 NULL 并且任何返回值都將會(huì)被忽略。這種情況可以通過(guò)檢測(cè)info->analyze_only
來(lái)區(qū)分。我們建議,在這樣的調(diào)用中訪問(wèn)方法除了做插入后的清理之外什么也不做,并且那是僅僅是在一個(gè)自動(dòng)清理工作者進(jìn)程中。
bool
amcanreturn (Relation indexRelation, int attno);
通過(guò)返回型為一個(gè)IndexTuple
的索引項(xiàng)的被索引列值,檢查索引是否能在給定列上支持只用索引的掃描。屬性編號(hào)從 1 開(kāi)始編號(hào),即第一列的 attno 是 1。如果支持返回 TRUE,否則返回 FALSE。如果訪問(wèn)方法
完全不支持只用索引的掃描,其IndexAmRoutine
結(jié)構(gòu)中的amcanreturn
域可以被設(shè)置為 NULL。
void
amcostestimate (PlannerInfo *root,
IndexPath *path,
double loop_count,
Cost *indexStartupCost,
Cost *indexTotalCost,
Selectivity *indexSelectivity,
double *indexCorrelation,
double *indexPages);
估計(jì)一次索引掃描的開(kāi)銷。這個(gè)函數(shù)在下面的第 61.6 節(jié)中有完整的討論。
bytea *
amoptions (ArrayType *reloptions,
bool validate);
分析和驗(yàn)證一個(gè)索引的 reloptions 數(shù)組。僅當(dāng)一個(gè)索引存在非空 reloptions 數(shù)組時(shí)才會(huì)被調(diào)用。reloptions
是一個(gè)text
數(shù)組,包含name
=
value
形式的項(xiàng)。
該函數(shù)應(yīng)當(dāng)構(gòu)建一個(gè)bytea
值,該值將被拷貝進(jìn)索引的 relcache 項(xiàng)的rd_options
域。bytea
值的數(shù)據(jù)內(nèi)容是開(kāi)放由訪問(wèn)方法定義的, 大部分的標(biāo)準(zhǔn)訪問(wèn)方法都使用StdRdOptions
結(jié)構(gòu)。當(dāng)validate
為真時(shí),如果任何一個(gè)選項(xiàng)都不可識(shí)別或者含有非法值,該函數(shù)都應(yīng)當(dāng)報(bào)告一個(gè)適當(dāng)?shù)腻e(cuò)誤消息;當(dāng)
validate
為假時(shí),非法 項(xiàng)應(yīng)該被安靜地忽略(當(dāng)正在載入的選項(xiàng)已經(jīng)在pg_catalog
中時(shí), validate
為假;僅在訪問(wèn)方法已經(jīng)改變了選項(xiàng)的規(guī)則時(shí)才可能找 到非法項(xiàng),并且在此情況下忽略廢棄的項(xiàng)是合適的)。如果想要默認(rèn)行為,那么返回 NULL 也 OK。
bool
amproperty (Oid index_oid, int attno,
IndexAMProperty prop, const char *propname,
bool *res, bool *isnull);
amproperty
方法允許索引方法覆蓋pg_index_column_has_property
和相關(guān)函數(shù)的默認(rèn)行為。如果訪問(wèn)方法對(duì)于索引性質(zhì)查詢沒(méi)有指定特殊的行為,其IndexAmRoutine
結(jié)構(gòu)的amproperty
域可以被設(shè)置為 NULL。否則,對(duì)于
pg_indexam_has_property
調(diào)用會(huì)使用均為 0 的index_oid
和attno
參數(shù)來(lái)調(diào)用amproperty
方法;對(duì)于pg_index_has_property
調(diào)用會(huì)使用有效的index_oid
和為
0 的attno
參數(shù)來(lái)調(diào)用amproperty
方法;對(duì)于pg_index_column_has_property
調(diào)用會(huì)使用有效的index_oid
以及大于零的attno
參數(shù)來(lái)調(diào)用
amproperty
方法。prop
是用于標(biāo)識(shí)被測(cè)試性質(zhì)的枚舉值,而propname
是原始的性質(zhì)名稱字符串。如果核心代碼不能識(shí)別該性質(zhì)名稱,則prop
為AMPROP_UNKNOWN
。訪問(wèn)方法可以通過(guò)檢查
propname
是否匹配(為與核心代碼一致,使用pg_strcasecmp
來(lái)匹配)來(lái)定義自定義性質(zhì)名稱;對(duì)于核心代碼已知的名稱,最好檢查prop
。 如果amproperty
方法返回true
則表示它已經(jīng)確定了性質(zhì)測(cè)試的結(jié)果:它必定會(huì)設(shè)置*res
為要返回的布爾值,如果要返回
NULL 則設(shè)置*isnull
為true
(兩個(gè)被引用的變量在調(diào)用之前要被初始化為false
)。如果amproperty
方法返回false
則核心代碼將會(huì)用其通常的邏輯來(lái)確定性質(zhì)測(cè)試的結(jié)果。
支持排序操作符的訪問(wèn)方法應(yīng)該實(shí)現(xiàn)AMPROP_DISTANCE_ORDERABLE
性質(zhì)測(cè)試,因?yàn)楹诵拇a不知道如何做該測(cè)試并且會(huì)返回 NULL。如果有比打開(kāi)索引并調(diào)用amcanreturn
(這是核心代碼的默認(rèn)行為)更廉價(jià)的方法來(lái)做AMPROP_RETURNABLE
測(cè)試,最好也實(shí)現(xiàn)它。默認(rèn)行為應(yīng)該對(duì)所有其他標(biāo)準(zhǔn)性質(zhì)是符合要求的。
char *
ambuildphasename (int64 phasenum);
返回給定構(gòu)建相數(shù)號(hào)碼的文本名稱。 相數(shù)號(hào)碼是在通過(guò)pgstat_progress_update_param
接口構(gòu)建索引期間報(bào)告的. 然后相數(shù)號(hào)碼在pg_stat_progress_create_index
視圖中公開(kāi)。
bool
amvalidate (Oid opclassoid);
只要訪問(wèn)方法能夠,為指定的操作符類驗(yàn)證系統(tǒng)目錄項(xiàng)。例如,這可能包括所有所需支持函數(shù)所提供的測(cè)試。如果該 opclass 不合法,amvalidate
函數(shù)必須返回假。所存在的問(wèn)題應(yīng)由ereport
消息報(bào)告。
當(dāng)然,索引的目的是支持掃描那些匹配一個(gè)可索引WHERE
情況的元組,常常也被稱為限定詞或掃描鍵。索引掃描的語(yǔ)義在下面的第 61.3 節(jié)中有完整的描述。一個(gè)索引訪問(wèn)方法可以支持
“普通”索引掃描、“位圖”索引掃描或者兩者。一個(gè)索引訪問(wèn)方法必須或可能提供的與掃描相關(guān)的函數(shù)是:
IndexScanDesc
ambeginscan (Relation indexRelation,
int nkeys,
int norderbys);
為一個(gè)索引掃描做準(zhǔn)備。nkeys
和norderbys
參數(shù)說(shuō)明要被用在掃描中的條件和排序操作符的數(shù)目,它們可以用于空間分配目的。注意掃描鍵的實(shí)際值還沒(méi)有被提供。結(jié)果必須是一個(gè) palloc 過(guò)的結(jié)構(gòu)。由于實(shí)現(xiàn)的原因,索引訪問(wèn)方法必須通過(guò)調(diào)用RelationGetIndexScan()
來(lái)創(chuàng)建這個(gè)結(jié)構(gòu)。在大多數(shù)情況中,
ambeginscan
除了做這個(gè)調(diào)用和獲取鎖之外不會(huì)做很多工作,索引掃描啟動(dòng)中有趣的部分在amrescan
中。
void
amrescan (IndexScanDesc scan,
ScanKey keys,
int nkeys,
ScanKey orderbys,
int norderbys);
開(kāi)始或者重新開(kāi)始一個(gè)索引掃描,可能使用的是一個(gè)新的掃描鍵(要想使用之前傳遞的鍵重新開(kāi)始,給keys
和/或orderbys
傳遞 NULL)。請(qǐng)注意,使用的鍵或排序操作符的個(gè)數(shù)不能大于傳遞給ambeginscan
的個(gè)數(shù)。實(shí)際上這個(gè)重新開(kāi)始特性的使用場(chǎng)景是:在一個(gè)嵌套循環(huán)連接選取了一個(gè)新的 outer 元組時(shí),因此需要一個(gè)新的鍵比較值,但掃描鍵結(jié)構(gòu)仍然保持相同。
boolean
amgettuple (IndexScanDesc scan,
ScanDirection direction);
在給定掃描中取下一個(gè)元組,向給定方向移動(dòng)(在索引中向前或者向后)。如果取到了元組,則返回 TRUE,如果取到匹配的元組,返回 FALSE。在 TRUE 的情況中,該元組的 TID 被存儲(chǔ)在scan
結(jié)構(gòu)中。請(qǐng)注意“成功”只 意味著索引包含一個(gè)匹配掃描鍵的項(xiàng),并不意味該元組仍然在堆中存在, 或者是能夠通過(guò)調(diào)用者的快照測(cè)試。在成功時(shí),
amgettuple
也必須把scan->xs_recheck
設(shè) 置成 TRUE 或者 FALSE。FALSE 意味著它確定索引項(xiàng)匹配掃描鍵。TRUE 意味著它并不確定,而且必須在取得堆元組之后對(duì)它重新檢查掃描鍵表示的條件。 這條規(guī)定支持“有損的”索引操作符。注意重新檢查僅僅對(duì)掃描條件擴(kuò)展;一個(gè)部分索引謂語(yǔ)(如果有)從不被
amgettuple
調(diào)用者重新檢查。
如果索引支持只用索引掃描(即amcanreturn
對(duì)它返回 TRUE),則在成功時(shí) AM 也必須檢查scan->xs_want_itup
,并且如果檢查為真它必須返回索引項(xiàng)的原始被索引數(shù)據(jù)。該數(shù)據(jù)的返回形式可以是一個(gè)存儲(chǔ)在
scan->xs_itup
中的IndexTuple
指針外加元組描述符scan->xs_itupdesc
,或者是一個(gè)存儲(chǔ)在scan->xs_hitup
中的HeapTuple
指針外加元組描述符scan->xs_hitupdesc
(在重構(gòu)可能無(wú)法放在一個(gè)
IndexTuple
中的數(shù)據(jù)時(shí),應(yīng)該使用后一種格式)。不管是哪種形式,訪問(wèn)方法應(yīng)該負(fù)責(zé)管理好指針引用的數(shù)據(jù)。至少在為掃描下一次調(diào)用amgettuple
、amrescan
或amendscan
之前,該數(shù)據(jù)必須是完好的。
如果訪問(wèn)方法支持“普通”索引掃描,只需要提供amgettuple
函數(shù)。如果不支持,它的IndexAmRoutine
結(jié)構(gòu)的amgettuple
域必須被設(shè)置為 NULL。
int64
amgetbitmap (IndexScanDesc scan,
TIDBitmap *tbm);
在給定掃描中取所有元組并且把它們添加到調(diào)用者提供的TIDBitmap
中(即,把元組 ID 的集合 OR 到已經(jīng)存在于位圖中的東西里面)。返回被取得的元組的數(shù)量(這可能僅僅是一個(gè)近似計(jì)數(shù),例如一些 AM 不會(huì)去重)。在把元組 ID 插入到位圖時(shí),amgetbitmap
可以指明對(duì)指定元組 ID 要求重新檢查掃描條件。這與amgettuple
的
xs_recheck
輸出參數(shù)類似。注意:在當(dāng)前的實(shí)現(xiàn)中,這個(gè)特性的支持是和對(duì)位圖本身有損存儲(chǔ)的支持合并在一起的,并且調(diào)用者會(huì)對(duì)可重新檢查的元組檢查掃描條件和部分索引謂詞(如果有)。但是,那不會(huì)總是真的。amgetbitmap
和amgettuple
不能被用于同一個(gè)索引掃描;正如第 61.3 節(jié)中所解釋的,在使用
amgetbitmap
時(shí)也有其他的限制條件。
如果訪問(wèn)方法支持“bitmap”索引掃描,則僅需要提供amgetbitmap
函數(shù)。如果不支持,它的IndexAmRoutine
結(jié)構(gòu)中的amgetbitmap
域必須被設(shè)置為 NULL。
void
amendscan (IndexScanDesc scan);
結(jié)束掃描并釋放資源。不應(yīng)該釋放scan
結(jié)構(gòu)本身,但訪問(wèn)方法內(nèi)部使用的任何鎖或者 pin 都應(yīng)該被釋放, 以及ambeginscan
和其他掃描相關(guān)函數(shù)分配的任何其他內(nèi)存。
void
ammarkpos (IndexScanDesc scan);
標(biāo)記當(dāng)前掃描位置。訪問(wèn)方法只需要支持每個(gè)掃描里面有一個(gè)被標(biāo)記的掃描位置。
ammarkpos
函數(shù)只有在訪問(wèn)方法支持有序掃描時(shí)才需要提供。如果不支持,則訪問(wèn)方法的IndexAmRoutine
結(jié)構(gòu)的ammarkpos
域可以設(shè)置為 NULL。
void
amrestrpos (IndexScanDesc scan);
把掃描恢復(fù)到最近標(biāo)記的位置。
amrestrpos
函數(shù)只有在訪問(wèn)方法支持有序掃描時(shí)才需要提供。如果不支持,則訪問(wèn)方法的IndexAmRoutine
結(jié)構(gòu)的amrestrpos
域可以設(shè)置為 NULL。
除了支持普通的索引掃描之外,某些類型的索引可能希望支持并行索引掃描,這種方式允許多個(gè)后端合作來(lái)執(zhí)行一次索引掃描。索引訪問(wèn)方法應(yīng)該安排好各種事情,這樣每個(gè)參與合作的進(jìn)程才能返回原本會(huì)由普通非并行索引掃描執(zhí)行得到的元組的一個(gè)子集,但是得到的那些子集的并集應(yīng)該等于普通非并行索引掃描得到的元組集合。此外,雖然不需要并行掃描返回的元組有任何全局順序,但每個(gè)參與合作的后端中返回的元組子集的順序必須匹配所要求的順序。必須實(shí)現(xiàn)下列函數(shù)才能支持并行索引掃描:
Size
amestimateparallelscan (void);
估算并且返回訪問(wèn)方法執(zhí)行一次并行掃描所需要的動(dòng)態(tài)共享內(nèi)存的字節(jié)數(shù)(這個(gè)數(shù)字是對(duì)ParallelIndexScanDescData
中訪問(wèn)方法無(wú)關(guān)的數(shù)據(jù)所需空間量的補(bǔ)充而不是替代)。
對(duì)于不支持并行掃描或者額外存儲(chǔ)需求的的字節(jié)數(shù)為零的訪問(wèn)方法,無(wú)需實(shí)現(xiàn)這個(gè)函數(shù)。
void
aminitparallelscan (void *target);
在一次并行掃描的開(kāi)頭將調(diào)用這個(gè)函數(shù)來(lái)初始化動(dòng)態(tài)共享內(nèi)存。target
將指向一段動(dòng)態(tài)共享內(nèi)存空間,其大小至少為之前amestimateparallelscan
返回的字節(jié)數(shù),并且這個(gè)函數(shù)可以使用這部分空間來(lái)存放它希望存放的任何數(shù)據(jù)。
對(duì)于不支持并行掃描或者不要求初始化共享內(nèi)存空間的情況,無(wú)需實(shí)現(xiàn)這個(gè)函數(shù)。
void
amparallelrescan (IndexScanDesc scan);
如果實(shí)現(xiàn)了這個(gè)函數(shù),當(dāng)并行索引掃描必須被重啟時(shí),將會(huì)調(diào)用這個(gè)函數(shù)。它應(yīng)該重置由aminitparallelscan
建立的任何共享狀態(tài),這樣掃描將會(huì)被重頭重新開(kāi)始。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: