每個索引存取方法都由 pg_am
系統目錄中的一個列描述。pg_am
條目指定索引存取方法的名稱和處理函數。可以使用 CREATE ACCESS METHOD 和 DROP ACCESS METHOD SQL 命令建立和刪除這些條目。
索引存取方法處理函數必須宣告為接受單一 internal
型別的引數,並傳回偽型別 index_am_handler
。該引數是一個虛擬值,僅用於防止處理函數直接從 SQL 命令呼叫。函數的結果必須是 palloc'd 型別的結構 IndexAmRoutine
,其中包含核心程式碼需要知道的所有內容,以使用索引存取方法。IndexAmRoutine
結構,也稱為存取方法的API 結構,包括指定存取方法各種固定屬性的欄位,例如它是否可以支援多欄索引。更重要的是,它包含指向存取方法的支援函數的指標,這些函數執行存取索引的所有實際工作。這些支援函數是普通的 C 函數,在 SQL 層級不可見或無法呼叫。支援函數在第 62.2 節中說明。
結構 IndexAmRoutine
的定義如下
typedef struct IndexAmRoutine { NodeTag type; /* * Total number of strategies (operators) by which we can traverse/search * this AM. Zero if AM does not have a fixed set of strategy assignments. */ uint16 amstrategies; /* total number of support functions that this AM uses */ uint16 amsupport; /* opclass options support function number or 0 */ uint16 amoptsprocnum; /* does AM support ORDER BY indexed column's value? */ bool amcanorder; /* does AM support ORDER BY result of an operator on indexed column? */ bool amcanorderbyop; /* does AM support backward scanning? */ bool amcanbackward; /* does AM support UNIQUE indexes? */ bool amcanunique; /* does AM support multi-column indexes? */ bool amcanmulticol; /* does AM require scans to have a constraint on the first index column? */ bool amoptionalkey; /* does AM handle ScalarArrayOpExpr quals? */ bool amsearcharray; /* does AM handle IS NULL/IS NOT NULL quals? */ bool amsearchnulls; /* can index storage data type differ from column data type? */ bool amstorage; /* can an index of this type be clustered on? */ bool amclusterable; /* does AM handle predicate locks? */ bool ampredlocks; /* does AM support parallel scan? */ bool amcanparallel; /* does AM support parallel build? */ bool amcanbuildparallel; /* does AM support columns included with clause INCLUDE? */ bool amcaninclude; /* does AM use maintenance_work_mem? */ bool amusemaintenanceworkmem; /* does AM summarize tuples, with at least all tuples in the block * summarized in one summary */ bool amsummarizing; /* OR of parallel vacuum flags */ uint8 amparallelvacuumoptions; /* type of data stored in index, or InvalidOid if variable */ Oid amkeytype; /* interface functions */ ambuild_function ambuild; ambuildempty_function ambuildempty; aminsert_function aminsert; aminsertcleanup_function aminsertcleanup; ambulkdelete_function ambulkdelete; amvacuumcleanup_function amvacuumcleanup; amcanreturn_function amcanreturn; /* can be NULL */ amcostestimate_function amcostestimate; amoptions_function amoptions; amproperty_function amproperty; /* can be NULL */ ambuildphasename_function ambuildphasename; /* can be NULL */ amvalidate_function amvalidate; amadjustmembers_function amadjustmembers; /* can be NULL */ ambeginscan_function ambeginscan; amrescan_function amrescan; amgettuple_function amgettuple; /* can be NULL */ amgetbitmap_function amgetbitmap; /* can be NULL */ amendscan_function amendscan; ammarkpos_function ammarkpos; /* can be NULL */ amrestrpos_function amrestrpos; /* can be NULL */ /* interface functions to support parallel index scans */ amestimateparallelscan_function amestimateparallelscan; /* can be NULL */ aminitparallelscan_function aminitparallelscan; /* can be NULL */ amparallelrescan_function amparallelrescan; /* can be NULL */ } IndexAmRoutine;
為了有用,索引存取方法還必須在 pg_opfamily
、pg_opclass
、pg_amop
和 pg_amproc
中定義一個或多個運算子族和運算子類別。這些條目允許計畫器確定哪些查詢條件可以使用此存取方法的索引。運算子族和類別在第 36.16 節中說明,這是閱讀本章的先決條件材料。
個別索引由 pg_class
條目定義,該條目將其描述為一個實體關係,加上一個 pg_index
條目,該條目顯示索引的邏輯內容 — 也就是說,它具有的索引欄位集以及這些欄位的語意,如關聯的運算子類別所擷取。索引欄位(鍵值)可以是底層表格的簡單欄位,也可以是表格列上的運算式。索引存取方法通常對索引鍵值的來源沒有興趣(它始終會收到預先計算的鍵值),但它會對 pg_index
中的運算子類別資訊非常感興趣。這兩個目錄條目都可以作為傳遞給索引上所有作業的 Relation
資料結構的一部分存取。
IndexAmRoutine
的某些旗標欄位具有不明顯的含義。amcanunique
的需求在第 62.5 節中討論。amcanmulticol
旗標表示存取方法支援多鍵欄位索引,而 amoptionalkey
表示它允許掃描,其中未給出第一個索引欄位的可索引限制子句。當 amcanmulticol
為 false 時,amoptionalkey
實際上表示存取方法是否支援沒有任何限制子句的完整索引掃描。支援多個索引欄位的存取方法必須支援省略對第一個欄位之後的任何或所有欄位的限制的掃描;但是,允許它們要求第一個索引欄位出現一些限制,這透過設定 amoptionalkey
false 來表示。索引的原因之一是AM如果索引沒有為空值建立索引,則可能會將 amoptionalkey
設定為 false。因為大多數可建立索引的運算子都是嚴格的,因此無法為空值輸入傳回 true,乍看之下,不為空值儲存索引條目似乎很吸引人:它們無論如何都不會被索引掃描傳回。但是,當索引掃描沒有給定索引欄位的限制子句時,此論點就會失效。實際上,這表示 amoptionalkey
為 true 的索引必須為空值建立索引,因為規劃器可能會決定使用沒有掃描鍵的此類索引。一個相關的限制是,支援多個索引欄位的索引存取方法必須支援為第一個欄位之後的欄位中的空值建立索引,因為規劃器會假設該索引可用於不限制這些欄位的查詢。例如,考慮 (a,b) 上的索引和具有 WHERE a = 4
的查詢。系統會假設該索引可用於掃描具有 a = 4
的資料列,如果索引省略了 b
為空值的資料列,則這是錯誤的。但是,省略第一個索引欄位為空值的資料列是可以的。執行空值索引的索引存取方法也可以設定 amsearchnulls
,表示它支援 IS NULL
和 IS NOT NULL
子句作為搜尋條件。
amcaninclude
旗標表示存取方法是否支援「包含」欄位,也就是說,它可以儲存(無需處理)金鑰欄位之外的其他欄位。前一段的要求僅適用於金鑰欄位。特別是,amcanmulticol
=false
和 amcaninclude
=true
的組合是有意義的:這表示只能有一個金鑰欄位,但也可以有包含的欄位。此外,無論 amoptionalkey
如何,都必須允許包含的欄位為空值。
amsummarizing
旗標表示存取方法是否摘要索引的元組,摘要的粒度至少為每個區塊。不指向個別元組,而是指向區塊範圍(例如BRIN)的存取方法,可能會允許HOT最佳化繼續。這不適用於索引謂詞中引用的屬性,此類屬性的更新始終會停用HOT.
如果您在文件中看到任何不正確、與特定功能的體驗不符或需要進一步澄清的地方,請使用此表單回報文件問題。