每個索引存取方法都由 pg_am
系統目錄中的一行來描述。pg_am
項目指定索引存取方法的名稱和處理函式。可以使用 CREATE ACCESS METHOD 和 DROP ACCESS METHOD SQL 命令來建立和刪除這些項目。
必須宣告索引存取方法處理函式,以接受 internal
類型的一個引數,並傳回偽類型 index_am_handler
。該引數是一個虛擬值,僅用於防止直接從 SQL 命令呼叫處理函式。該函式的結果必須是一個 palloc 的 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.
如果您在文件中發現任何不正確、與您對特定功能的體驗不符或需要進一步澄清的地方,請使用此表單來報告文件問題。