Postgresql 中文操作指南
64.2. Index Access Method Functions #
索引访问方法必须在 IndexAmRoutine 中提供的索引构造和维护功能是:
The index construction and maintenance functions that an index access method must provide in IndexAmRoutine are:
IndexBuildResult *
ambuild (Relation heapRelation,
Relation indexRelation,
IndexInfo *indexInfo);
构建新索引。索引关系已物理创建,但为空。它必须填充访问方法需要的任何固定数据,以及表中所有现有元组的条目。通常,ambuild 函数将调用 table_index_build_scan() 来扫描表以获取现有元组,并计算需要插入索引的键。此函数必须返回一个已分配帕洛克的结构,其中包含有关新索引的统计信息。
Build a new index. The index relation has been physically created, but is empty. It must be filled in with whatever fixed data the access method requires, plus entries for all tuples already existing in the table. Ordinarily the ambuild function will call table_index_build_scan() to scan the table for existing tuples and compute the keys that need to be inserted into the index. The function must return a palloc’d struct containing statistics about the new index.
void
ambuildempty (Relation indexRelation);
构建一个空索引,并将其写入给定关系的初始化分支(INIT_FORKNUM)。仅对未记录索引调用此方法;写入初始化分支的空索引将在每次服务器重新启动时复制到主关系分支。
Build an empty index, and write it to the initialization fork (INIT_FORKNUM) of the given relation. This method is called only for unlogged indexes; the empty index written to the initialization fork will be copied over the main relation fork on each server restart.
bool
aminsert (Relation indexRelation,
Datum *values,
bool *isnull,
ItemPointer heap_tid,
Relation heapRelation,
IndexUniqueCheck checkUnique,
bool indexUnchanged,
IndexInfo *indexInfo);
将新元组插入现有索引。数组 values 和 isnull 提供要索引的关键值,而 heap_tid 是要索引的 TID。如果访问方法支持唯一的索引(其 amcanunique 标志为 true),那么 checkUnique 指示要执行的唯一性检查的类型。这会因唯一约束是否可延迟而异;有关详细信息,请参见 Section 64.5。通常,访问方法仅在执行唯一性检查时才需要 heapRelation 参数(因为那时它必须查看堆以验证元组生存期)。
Insert a new tuple into an existing index. The values and isnull arrays give the key values to be indexed, and heap_tid is the TID to be indexed. If the access method supports unique indexes (its amcanunique flag is true) then checkUnique indicates the type of uniqueness check to perform. This varies depending on whether the unique constraint is deferrable; see Section 64.5 for details. Normally the access method only needs the heapRelation parameter when performing uniqueness checking (since then it will have to look into the heap to verify tuple liveness).
indexUnchanged 布尔值提示要编制索引的元组的性质。当它为 true 时,元组是索引中某个现有元组的副本。新元组是一个逻辑上未更改的后继 MVCC 元组版本。当发生 UPDATE 时会出现这种情况,该操作不会修改索引涵盖的任何列,但是仍然需要索引中有一个新版本。索引 AM 可以使用此提示来决定对相同逻辑行大量版本累积的索引部分应用自底向上索引删除。请注意,更新非键列或仅出现在部分索引谓词中的列不会影响 indexUnchanged 的值。核心代码使用低开销方法确定每个元组的 indexUnchanged 值,该方法允许假阳性和假阴性。索引 AM 不能将 indexUnchanged 视为有关元组可见性或版本控制的权威信息源。
The indexUnchanged Boolean value gives a hint about the nature of the tuple to be indexed. When it is true, the tuple is a duplicate of some existing tuple in the index. The new tuple is a logically unchanged successor MVCC tuple version. This happens when an UPDATE takes place that does not modify any columns covered by the index, but nevertheless requires a new version in the index. The index AM may use this hint to decide to apply bottom-up index deletion in parts of the index where many versions of the same logical row accumulate. Note that updating a non-key column or a column that only appears in a partial index predicate does not affect the value of indexUnchanged. The core code determines each tuple’s indexUnchanged value using a low overhead approach that allows both false positives and false negatives. Index AMs must not treat indexUnchanged as an authoritative source of information about tuple visibility or versioning.
此函数的布尔结果值仅在 checkUnique 为 UNIQUE_CHECK_PARTIAL 时才重要。在这种情况下,如果结果为 true,则表示已知新条目是唯一的,而 false 表示它可能不是唯一的(并且必须调度延迟唯一性检查)。对于其他情况,建议返回恒定的 false 结果。
The function’s Boolean result value is significant only when checkUnique is UNIQUE_CHECK_PARTIAL. In this case a true result means the new entry is known unique, whereas false means it might be non-unique (and a deferred uniqueness check must be scheduled). For other cases a constant false result is recommended.
某些索引可能不会索引所有元组。如果元组不应该被索引,aminsert 应该返回而什么都不做。
Some indexes might not index all tuples. If the tuple is not to be indexed, aminsert should just return without doing anything.
如果索引 AM 希望在 SQL 语句中跨连续的索引插入缓存数据,则可以在 indexInfo→ii_Context 中分配空间,并在 indexInfo→ii_AmCache 中存储指向数据的指针(最初为 NULL)。
If the index AM wishes to cache data across successive index insertions within an SQL statement, it can allocate space in indexInfo→ii_Context and store a pointer to the data in indexInfo→ii_AmCache (which will be NULL initially).
IndexBulkDeleteResult *
ambulkdelete (IndexVacuumInfo *info,
IndexBulkDeleteResult *stats,
IndexBulkDeleteCallback callback,
void *callback_state);
从索引中删除元组。这是一种“批量删除”操作,旨在通过扫描整个索引并检查每个条目以查看是否应该删除它来实现。必须根据 callback(_TID 的样式(即 callback_state)returns bool_)来调用传入的 callback 函数,以确定通过其引用的 TID 识别的任何特定索引条目是否要被删除。必须返回 NULL 或返回一个已分配帕洛克的结构,其中包含有关删除操作效果的统计信息。如果不需要将信息传递给 amvacuumcleanup,则返回 NULL 是可以的。
Delete tuple(s) from the index. This is a “bulk delete” operation that is intended to be implemented by scanning the whole index and checking each entry to see if it should be deleted. The passed-in callback function must be called, in the style callback(_TID, callback_state) returns bool_, to determine whether any particular index entry, as identified by its referenced TID, is to be deleted. Must return either NULL or a palloc’d struct containing statistics about the effects of the deletion operation. It is OK to return NULL if no information needs to be passed on to amvacuumcleanup.
因为 maintenance_work_mem 受限,所以当需要删除大量元组时可能需要多次调用 ambulkdelete。stats 参数是针对此索引的先前调用的结果(它是 VACUUM 操作中的第一次调用时为 NULL)。这使 AM 可以在整个操作中累积统计信息。通常,ambulkdelete 在 stats 不为 null 的情况下会修改并返回相同的结构。
Because of limited maintenance_work_mem, ambulkdelete might need to be called more than once when many tuples are to be deleted. The stats argument is the result of the previous call for this index (it is NULL for the first call within a VACUUM operation). This allows the AM to accumulate statistics across the whole operation. Typically, ambulkdelete will modify and return the same struct if the passed stats is not null.
IndexBulkDeleteResult *
amvacuumcleanup (IndexVacuumInfo *info,
IndexBulkDeleteResult *stats);
在 VACUUM 操作之后清理(零个或多个 ambulkdelete 调用)。除了返回索引统计信息之外,这不需要做任何事情,但它可以执行批量清理,例如回收空索引页面。stats 是最后一个 ambulkdelete 调用返回的任何值,或者如果 ambulkdelete 未被调用是因为不需要删除任何元组,则返回 NULL。如果结果不为 NULL 则它必须是一个已分配帕洛克的结构。它所包含的统计信息将用于更新 pg_class,并且如果给出了 VERBOSE,则将由 VACUUM 报告。如果在 VACUUM 操作期间索引根本没有被更改,则返回 NULL 是可以的,但否则应该返回正确的统计信息。
Clean up after a VACUUM operation (zero or more ambulkdelete calls). This does not have to do anything beyond returning index statistics, but it might perform bulk cleanup such as reclaiming empty index pages. stats is whatever the last ambulkdelete call returned, or NULL if ambulkdelete was not called because no tuples needed to be deleted. If the result is not NULL it must be a palloc’d struct. The statistics it contains will be used to update pg_class, and will be reported by VACUUM if VERBOSE is given. It is OK to return NULL if the index was not changed at all during the VACUUM operation, but otherwise correct stats should be returned.
amvacuumcleanup 也将在 ANALYZE 操作完成后被调用。在这种情况下,stats 始终为 NULL 并且将忽略任何返回值。可以通过检查 info→analyze_only 来区分这种情况。建议访问方法在这个调用中除了进行插入后清理操作之外什么都不做,并且仅在自动清理工作进程中进行。
amvacuumcleanup will also be called at completion of an ANALYZE operation. In this case stats is always NULL and any return value will be ignored. This case can be distinguished by checking info→analyze_only. It is recommended that the access method do nothing except post-insert cleanup in such a call, and that only in an autovacuum worker process.
bool
amcanreturn (Relation indexRelation, int attno);
通过返回给定列的原始索引值,检查索引是否可以对列支持 index-only scans 。属性编号从 1 开始,即第一个列的 attno 为 1。如果支持,则返回 true,否则返回 false。对于包括的列(如果支持),此功能应始终返回 true,因为对于无法检索的包括的列而言,它几乎没有意义。如果访问方法根本不支持仅索引扫描,则其 IndexAmRoutine 结构中的 amcanreturn 字段可以设置为 NULL。
Check whether the index can support index-only scans on the given column, by returning the column’s original indexed value. The attribute number is 1-based, i.e., the first column’s attno is 1. Returns true if supported, else false. This function should always return true for included columns (if those are supported), since there’s little point in an included column that can’t be retrieved. If the access method does not support index-only scans at all, the amcanreturn field in its IndexAmRoutine struct can be set to NULL.
void
amcostestimate (PlannerInfo *root,
IndexPath *path,
double loop_count,
Cost *indexStartupCost,
Cost *indexTotalCost,
Selectivity *indexSelectivity,
double *indexCorrelation,
double *indexPages);
估算索引扫描的成本。此函数在 Section 64.6 中进行了充分描述,它在下面。
Estimate the costs of an index scan. This function is described fully in Section 64.6, below.
bytea *
amoptions (ArrayType *reloptions,
bool validate);
解析并验证索引的 reloptions 数组。仅当索引存在非空 reloptions 数组时才会调用该数组。 reloptions 是 text 数组,其中包含 name=value 形式的条目。该函数应构造一个 bytea 值,该值将被复制到索引的 relcache 条目的 rd_options 字段中。 bytea 值的数据内容可由访问方法定义;大多数标准访问方法使用结构 StdRdOptions 。如果 validate 为 true,则在任何选项不被识别或值无效时,函数应报告一个合适的错误消息;如果 validate 为 false,则应忽略无效条目。(当在 pg_catalog 中加载已存储的选项时, validate 为 false;仅当访问方法更改了其选项规则时才会发现无效条目,在这种情况下,忽略已过时的条目是合适的。)如果需要默认行为,则返回 NULL 即可。
Parse and validate the reloptions array for an index. This is called only when a non-null reloptions array exists for the index. reloptions is a text array containing entries of the form name=value. The function should construct a bytea value, which will be copied into the rd_options field of the index’s relcache entry. The data contents of the bytea value are open for the access method to define; most of the standard access methods use struct StdRdOptions. When validate is true, the function should report a suitable error message if any of the options are unrecognized or have invalid values; when validate is false, invalid entries should be silently ignored. (validate is false when loading options already stored in pg_catalog; an invalid entry could only be found if the access method has changed its rules for options, and in that case ignoring obsolete entries is appropriate.) It is OK to return NULL if default behavior is wanted.
bool
amproperty (Oid index_oid, int attno,
IndexAMProperty prop, const char *propname,
bool *res, bool *isnull);
amproperty 方法允许索引访问方法覆盖 pg_index_column_has_property 和相关函数的默认行为。如果访问方法对索引属性查询没有任何特殊行为,则其 IndexAmRoutine 结构中的 amproperty 字段可以设置为 NULL。否则,当 index_oid 和 attno 都为 pg_indexam_has_property 调用为 0,或者当 index_oid 有效且 attno 为 pg_index_has_property 调用为 0,或者当 index_oid 有效且 attno 大于 pg_index_column_has_property 调用中的 0 时,将调用 amproperty 方法。prop 是一个枚举值,它标识正在测试的属性,而 propname 是原始属性名称字符串。如果核心代码不识别该属性名称,则 prop 为 AMPROP_UNKNOWN。访问方法可以通过检查 propname 匹配来自定义属性名称(使用 pg_strcasecmp 匹配,以保持与核心代码一致);对于核心代码知道的名称,最好检查 prop。如果 amproperty 方法返回 true,则它确定了属性测试结果:它必须将 *res 设置为要返回的布尔值,或者将 *isnull 设置为 true 以返回 NULL。(这两个引用的变量在调用之前都被初始化为 false。)如果 amproperty 方法返回 false,则核心代码将按照其确定属性测试结果的正常逻辑进行。
The amproperty method allows index access methods to override the default behavior of pg_index_column_has_property and related functions. If the access method does not have any special behavior for index property inquiries, the amproperty field in its IndexAmRoutine struct can be set to NULL. Otherwise, the amproperty method will be called with index_oid and attno both zero for pg_indexam_has_property calls, or with index_oid valid and attno zero for pg_index_has_property calls, or with index_oid valid and attno greater than zero for pg_index_column_has_property calls. prop is an enum value identifying the property being tested, while propname is the original property name string. If the core code does not recognize the property name then prop is AMPROP_UNKNOWN. Access methods can define custom property names by checking propname for a match (use pg_strcasecmp to match, for consistency with the core code); for names known to the core code, it’s better to inspect prop. If the amproperty method returns true then it has determined the property test result: it must set *res to the Boolean value to return, or set *isnull to true to return a NULL. (Both of the referenced variables are initialized to false before the call.) If the amproperty method returns false then the core code will proceed with its normal logic for determining the property test result.
支持排序运算符的访问方法应该实现 AMPROP_DISTANCE_ORDERABLE 属性测试,因为核心代码不知道如何执行此操作并且将返回 NULL。如果这样做比打开索引并调用 amcanreturn(这是核心代码的默认行为)更便宜,则实现 AMPROP_RETURNABLE 测试也可能是有利的。对于所有其他标准属性,默认行为应该是令人满意的。
Access methods that support ordering operators should implement AMPROP_DISTANCE_ORDERABLE property testing, as the core code does not know how to do that and will return NULL. It may also be advantageous to implement AMPROP_RETURNABLE testing, if that can be done more cheaply than by opening the index and calling amcanreturn, which is the core code’s default behavior. The default behavior should be satisfactory for all other standard properties.
char *
ambuildphasename (int64 phasenum);
返回给定构建阶段编号的文本名称。阶段编号是在 pgstat_progress_update_param 接口中索引构建期间报告的编号。然后将阶段名称显示在 pg_stat_progress_create_index 视图中。
Return the textual name of the given build phase number. The phase numbers are those reported during an index build via the pgstat_progress_update_param interface. The phase names are then exposed in the pg_stat_progress_create_index view.
bool
amvalidate (Oid opclassoid);
验证指定的运算符类的目录条目,只要访问方法可以合理地执行此操作。例如,这可能包括测试是否提供了所有必需的支持函数。如果 opclass 无效,amvalidate 函数必须返回 false。问题应该使用 ereport 消息报告,通常在 INFO 级别。
Validate the catalog entries for the specified operator class, so far as the access method can reasonably do that. For example, this might include testing that all required support functions are provided. The amvalidate function must return false if the opclass is invalid. Problems should be reported with ereport messages, typically at INFO level.
void
amadjustmembers (Oid opfamilyoid,
Oid opclassoid,
List *operators,
List *functions);
验证运算符系列的拟议新运算符和函数成员,只要访问方法可以合理地执行此操作,并设置它们的依赖类型(如果默认值不令人满意)。这在 CREATE OPERATOR CLASS 和 ALTER OPERATOR FAMILY ADD 期间被调用;在后一种情况下,opclassoid 为 InvalidOid。List 参数是 OpFamilyMember 结构的列表,如 amapi.h 中定义的。此函数执行的测试通常是 amvalidate 执行的测试的子集,因为 amadjustmembers 不能假设它看到的是一个完整的成员集。例如,检查支持函数的签名是合理的,而不是检查是否提供了所有必需的支持函数。可以通过抛出错误来报告任何问题。如果这是 CREATE OPERATOR CLASS,OpFamilyMember 结构的依赖相关字段由核心代码初始化,以创建对 opclass 的硬依赖关系;如果这是 ALTER OPERATOR FAMILY ADD
Validate proposed new operator and function members of an operator family, so far as the access method can reasonably do that, and set their dependency types if the default is not satisfactory. This is called during CREATE OPERATOR CLASS and during ALTER OPERATOR FAMILY ADD; in the latter case opclassoid is InvalidOid. The List arguments are lists of OpFamilyMember structs, as defined in amapi.h. Tests done by this function will typically be a subset of those performed by amvalidate, since amadjustmembers cannot assume that it is seeing a complete set of members. For example, it would be reasonable to check the signature of a support function, but not to check whether all required support functions are provided. Any problems can be reported by throwing an error. The dependency-related fields of the OpFamilyMember structs are initialized by the core code to create hard dependencies on the opclass if this is CREATE OPERATOR CLASS, or soft dependencies on the opfamily if this is ALTER OPERATOR FAMILY ADD. amadjustmembers can adjust these fields if some other behavior is more appropriate. For example, GIN, GiST, and SP-GiST always set operator members to have soft dependencies on the opfamily, since the connection between an operator and an opclass is relatively weak in these index types; so it is reasonable to allow operator members to be added and removed freely. Optional support functions are typically also given soft dependencies, so that they can be removed if necessary.
当然,索引的目的是支持扫描与可索引 WHERE 条件(通常称为 qualifier 或 scan key)匹配的元组。索引扫描的语义在 Section 64.3 中进行了更全面的描述,它在下面。索引访问方法可以支持“纯”索引扫描,“位图”索引扫描或两者兼而有之。索引访问方法必须或可能提供的与扫描相关的函数是:
The purpose of an index, of course, is to support scans for tuples matching an indexable WHERE condition, often called a qualifier or scan key. The semantics of index scanning are described more fully in Section 64.3, below. An index access method can support “plain” index scans, “bitmap” index scans, or both. The scan-related functions that an index access method must or may provide are:
IndexScanDesc
ambeginscan (Relation indexRelation,
int nkeys,
int norderbys);
准备索引扫描。 nkeys 和 norderbys 参数分别表示扫描中将使用的限定符和排序运算符的数量,这些在空间分配方面可能有帮助。需要注意的是,尚未提供扫描键的实际值。结果必须是 palloc 后的结构。出于实现方面的考虑,索引访问方法 must 通过调用 RelationGetIndexScan() 创建此结构。在大多数情况下,ambeginscan 除了通过该调用并可能获取锁定的操作,几乎没有什么其他操作;索引扫描启动的有趣部分在 amrescan 中。
Prepare for an index scan. The nkeys and norderbys parameters indicate the number of quals and ordering operators that will be used in the scan; these may be useful for space allocation purposes. Note that the actual values of the scan keys aren’t provided yet. The result must be a palloc’d struct. For implementation reasons the index access method must create this struct by calling RelationGetIndexScan(). In most cases ambeginscan does little beyond making that call and perhaps acquiring locks; the interesting parts of index-scan startup are in amrescan.
void
amrescan (IndexScanDesc scan,
ScanKey keys,
int nkeys,
ScanKey orderbys,
int norderbys);
以新的扫描键启动或重新启动索引扫描(若要使用先前传递键重新启动,应针对 keys 和/或 orderbys 传递 NULL)。请注意,键的数量或排序运算符的数量不允许大于传递给 ambeginscan 的值。在实践中,当嵌套循环联接选择了一个新的外部元组并因此需要一个新的键比较值时,但扫描键结构仍然相同,将使用重新启动功能。
Start or restart an index scan, possibly with new scan keys. (To restart using previously-passed keys, NULL is passed for keys and/or orderbys.) Note that it is not allowed for the number of keys or order-by operators to be larger than what was passed to ambeginscan. In practice the restart feature is used when a new outer tuple is selected by a nested-loop join and so a new key comparison value is needed, but the scan key structure remains the same.
bool
amgettuple (IndexScanDesc scan,
ScanDirection direction);
获取给定扫描中的下一个元组,并按给定方向(在索引中向前或向后)移动。如果获取了元组,则返回 true,如果未找到匹配的元组则返回 false。在 true 情况下,将元组 TID 存储到 scan 结构中。请注意,“成功”仅表示索引包含与扫描键匹配的一个条目,而不是元组必然仍然存在于堆中或将通过调用者的快照测试。成功时,amgettuple 还应将 scan→xs_recheck 设置为 true 或 false。False 表示确定索引条目与扫描键匹配。True 表示不确定,必须针对已获取的堆元组重新检查扫描键表示的条件。此规定支持“有损”索引运算符。请注意,重新检查只能针对扫描条件进行;amgettuple 调用方绝不会重新检查部分索引谓词(如果有)。
Fetch the next tuple in the given scan, moving in the given direction (forward or backward in the index). Returns true if a tuple was obtained, false if no matching tuples remain. In the true case the tuple TID is stored into the scan structure. Note that “success” means only that the index contains an entry that matches the scan keys, not that the tuple necessarily still exists in the heap or will pass the caller’s snapshot test. On success, amgettuple must also set scan→xs_recheck to true or false. False means it is certain that the index entry matches the scan keys. True means this is not certain, and the conditions represented by the scan keys must be rechecked against the heap tuple after fetching it. This provision supports “lossy” index operators. Note that rechecking will extend only to the scan conditions; a partial index predicate (if any) is never rechecked by amgettuple callers.
如果索引支持 index-only scans(即,amcanreturn 对其任何列返回 true),那么在成功的情况下,AM 还必须检查 scan→xs_want_itup,并且如果为 true,它必须返回索引项的原始索引数据。amcanreturn 返回 false 的列可以返回为 null。该数据可以以存储在 scan→xs_itup 处的 IndexTuple 指针的形式返回,并具有元组描述符 scan→xs_itupdesc;或者以存储在 scan→xs_hitup 处的 HeapTuple 指针的形式返回,并具有元组描述符 scan→xs_hitupdesc。(后一种格式应在重建可能不适合 IndexTuple 的数据时使用。)在任一情况下,对指针引用的数据的管理都是访问方法的责任。该数据至少在下次 amgettuple、amrescan 或针对扫描的 amendscan 调用之前保持良好状态。
If the index supports index-only scans (i.e., amcanreturn returns true for any of its columns), then on success the AM must also check scan→xs_want_itup, and if that is true it must return the originally indexed data for the index entry. Columns for which amcanreturn returns false can be returned as nulls. The data can be returned in the form of an IndexTuple pointer stored at scan→xs_itup, with tuple descriptor scan→xs_itupdesc; or in the form of a HeapTuple pointer stored at scan→xs_hitup, with tuple descriptor scan→xs_hitupdesc. (The latter format should be used when reconstructing data that might possibly not fit into an IndexTuple.) In either case, management of the data referenced by the pointer is the access method’s responsibility. The data must remain good at least until the next amgettuple, amrescan, or amendscan call for the scan.
只有在访问方法支持“普通”索引扫描时才需要提供 amgettuple 函数。如果它不支持,则其 IndexAmRoutine 结构中的 amgettuple 字段必须设置为 NULL。
The amgettuple function need only be provided if the access method supports “plain” index scans. If it doesn’t, the amgettuple field in its IndexAmRoutine struct must be set to NULL.
int64
amgetbitmap (IndexScanDesc scan,
TIDBitmap *tbm);
抓取给定扫描中的所有元组,并将它们添加到调用者提供的 TIDBitmap(即,将元组 ID 集合 OR 到位图中已经存在的任何集合中)。将返回抓取的元组数(这可能只是一个近似计数,例如,某些 AM 不会检测重复)。在将元组 ID 插入位图时,_amgetbitmap_可以指明需要对特定元组 ID 重新检查扫描条件。这类似于 _amgettuple_的 _xs_recheck_输出参数。注意:在当前实现中,对该功能的支持与对位图本身的无损存储的支持是混杂在一起的,因此调用者重新检查了扫描条件和部分索引谓词(如果有的话),以进行可重新检查的元组。但并非总是如此。_amgetbitmap_和 _amgettuple_不能在同一索引扫描中使用;在使用 _amgetbitmap_时也有其他限制,如 Section 64.3中所述。
Fetch all tuples in the given scan and add them to the caller-supplied TIDBitmap (that is, OR the set of tuple IDs into whatever set is already in the bitmap). The number of tuples fetched is returned (this might be just an approximate count, for instance some AMs do not detect duplicates). While inserting tuple IDs into the bitmap, amgetbitmap can indicate that rechecking of the scan conditions is required for specific tuple IDs. This is analogous to the xs_recheck output parameter of amgettuple. Note: in the current implementation, support for this feature is conflated with support for lossy storage of the bitmap itself, and therefore callers recheck both the scan conditions and the partial index predicate (if any) for recheckable tuples. That might not always be true, however. amgetbitmap and amgettuple cannot be used in the same index scan; there are other restrictions too when using amgetbitmap, as explained in Section 64.3.
只有在访问方法支持“位图”索引扫描时才需要提供 amgetbitmap 函数。如果它不支持,则其 IndexAmRoutine 结构中的 amgetbitmap 字段必须设置为 NULL。
The amgetbitmap function need only be provided if the access method supports “bitmap” index scans. If it doesn’t, the amgetbitmap field in its IndexAmRoutine struct must be set to NULL.
void
amendscan (IndexScanDesc scan);
结束扫描并释放资源。scan 结构本身不应该被释放,但是必须释放访问方法内部获取的任何锁或引脚,以及 ambeginscan 和其他扫描相关函数分配的任何其他内存。
End a scan and release resources. The scan struct itself should not be freed, but any locks or pins taken internally by the access method must be released, as well as any other memory allocated by ambeginscan and other scan-related functions.
void
ammarkpos (IndexScanDesc scan);
标记当前扫描位置。访问方法只需支持每个扫描一个已记住的扫描位置。
Mark current scan position. The access method need only support one remembered scan position per scan.
只有在访问方法支持有序扫描时才需要提供 ammarkpos 函数。如果它不支持,则其 IndexAmRoutine 结构中的 ammarkpos 字段可以设置为 NULL。
The ammarkpos function need only be provided if the access method supports ordered scans. If it doesn’t, the ammarkpos field in its IndexAmRoutine struct may be set to NULL.
void
amrestrpos (IndexScanDesc scan);
将扫描还原到最近标记的位置。
Restore the scan to the most recently marked position.
只有在访问方法支持有序扫描时才需要提供 amrestrpos 函数。如果它不支持,则其 IndexAmRoutine 结构中的 amrestrpos 字段可以设置为 NULL。
The amrestrpos function need only be provided if the access method supports ordered scans. If it doesn’t, the amrestrpos field in its IndexAmRoutine struct may be set to NULL.
除了支持普通索引扫描之外,某些类型的索引可能希望支持 parallel index scans,它允许多个后端协同执行索引扫描。索引访问方法应安排所有事务,以便每个协同进程返回普通非并行索引扫描将执行的元组子集,但要求这些子集的并集等于普通非并行索引扫描将返回的元组集。此外,虽然由并行扫描返回的元组不一定要有全局顺序,但是每个协同后端内返回的元组子集的顺序必须与请求的顺序匹配。以下函数可用于支持并行索引扫描:
In addition to supporting ordinary index scans, some types of index may wish to support parallel index scans, which allow multiple backends to cooperate in performing an index scan. The index access method should arrange things so that each cooperating process returns a subset of the tuples that would be performed by an ordinary, non-parallel index scan, but in such a way that the union of those subsets is equal to the set of tuples that would be returned by an ordinary, non-parallel index scan. Furthermore, while there need not be any global ordering of tuples returned by a parallel scan, the ordering of that subset of tuples returned within each cooperating backend must match the requested ordering. The following functions may be implemented to support parallel index scans:
Size
amestimateparallelscan (void);
估计并返回访问方法执行并行扫描所需的动态共享内存字节数。(此数字是对 ParallelIndexScanDescData 中 AM 独立数据的所需空间的补充,而不是替代。)
Estimate and return the number of bytes of dynamic shared memory which the access method will be needed to perform a parallel scan. (This number is in addition to, not in lieu of, the amount of space needed for AM-independent data in ParallelIndexScanDescData.)
对于不支持并行扫描或所需额外存储字节数为零的访问方法,不必实现此函数。
It is not necessary to implement this function for access methods which do not support parallel scans or for which the number of additional bytes of storage required is zero.
void
aminitparallelscan (void *target);
在并行扫描开始时,将调用此函数以初始化动态共享内存。target 将至少指向之前由 amestimateparallelscan 返回的字节数,并且此函数可以使用该数量的空间来存储它希望的任何数据。
This function will be called to initialize dynamic shared memory at the beginning of a parallel scan. target will point to at least the number of bytes previously returned by amestimateparallelscan, and this function may use that amount of space to store whatever data it wishes.
对于不支持并行扫描的访问方法,或在不需要初始化共享内存空间的情况下,不必实现此函数。
It is not necessary to implement this function for access methods which do not support parallel scans or in cases where the shared memory space required needs no initialization.
void
amparallelrescan (IndexScanDesc scan);
如果必须重新启动并行索引扫描,则会调用此函数(如果已实现)。它应重置 aminitparallelscan 设置的任何共享状态,以便扫描从头开始重新启动。
This function, if implemented, will be called when a parallel index scan must be restarted. It should reset any shared state set up by aminitparallelscan such that the scan will be restarted from the beginning.