# 62.1.索引的基本API结构

每个索引访问方法在普甘系统目录。这个普甘条目指定名称和名称处理函数对于索引访问方法。可以使用创建访问方法直接存取法SQL命令。

必须声明索引访问方法处理程序函数以接受类型为的单个参数内部的并返回伪类型索引处理程序.参数是一个伪值,用于防止直接从SQL命令调用处理程序函数。函数的结果必须是类型为的palloc结构索引路线,它包含核心代码使用索引访问方法所需的所有信息。这个索引路线结构,也称为访问方法的API结构,包括指定access方法的各种固定属性的字段,例如它是否支持多列索引。更重要的是,它包含支持access方法函数的指针,这些函数完成了访问索引的所有实际工作。这些支持函数是普通的C函数,在SQL级别不可见或不可调用。支持功能如中所述第62.2节.

结构索引路线定义如下:

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 columns included with clause INCLUDE? */
    bool        amcaninclude;
    /* does AM use maintenance_work_mem? */
    bool        amusemaintenanceworkmem;
    /* 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;
    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_家族, pg_类, 阿莫普安普罗克酒店。这些条目允许计划者确定什么样的查询资格可以与此访问方法的索引一起使用。中介绍了运算符族和类第38.16节,这是阅读本章的必备材料。

单个索引由pg_类将其描述为物理关系的条目,以及pg_指数显示索引的逻辑内容的项,即它所具有的索引列集以及这些列的语义,如关联的运算符类所捕获的。索引列(键值)可以是基础表的简单列,也可以是表行上的表达式。索引访问方法通常对索引键值来自何处不感兴趣(它总是被交给预计算键值),但它对中的运算符类信息非常感兴趣pg_指数。这两个目录条目都可以作为关系传递给索引上所有操作的数据结构。

一些国旗区索引路线具有不明显的含义。要求amcanunique将在中讨论第62.5节这个阿姆坎多科flag断言访问方法支持多键列索引,而A可选钥匙断言它允许在没有为第一个索引列提供可索引限制子句的情况下进行扫描。什么时候阿姆坎多科是假的,A可选钥匙本质上说,访问方法是否支持无任何限制子句的完整索引扫描。支持多个索引列的访问方法必须支持在第一列之后忽略对任何或所有列的限制的扫描;但是,允许它们要求对第一个索引列显示一些限制,这通过设置来表示A可选钥匙错误的可能会设置索引AM的一个原因A可选钥匙false是指它没有索引空值。由于大多数可索引运算符都是严格的,因此对于null输入不能返回true,所以乍一看不存储null值的索引项是很有吸引力的:无论如何,索引扫描都不能返回它们。但是,当索引扫描没有针对给定索引列的限制子句时,此参数将失败。实际上,这意味着A可选钥匙true必须为空索引,因为规划者可能会决定使用这样一个根本没有扫描键的索引。一个相关的限制是支持多个索引列的索引访问方法必须支持在第一列之后为列中的空值编制索引,因为计划者将假定索引可用于不限制这些列的查询。例如,考虑一个索引(a,b)和一个查询其中a=4.系统将假定索引可用于扫描具有a = 4,如果索引省略了行,这是错误的b一片空白。但是,可以忽略第一个索引列为空的行。执行索引空值的索引访问方法也可以设置amsearchnulls,表示它支持一片空白不为空子句作为搜索条件。

可以包括flag 指示访问方法是否支持“包含”列,即它可以存储(不处理)键列之外的其他列。前款的要求仅适用于关键栏目。特别是,结合amcanmulticol=错误的可以包括=真的是明智的:这意味着只能有一个键列,但也可以包含列。此外,必须允许包含的列为空,独立于可选键.