# 62.2.索引访问方法函数
索引访问方法在中必须提供的索引构造和维护功能索引路线
是:
IndexBuildResult *
ambuild (Relation heapRelation,
Relation indexRelation,
IndexInfo *indexInfo);
建立一个新的索引。索引关系已物理创建,但为空。它必须填充access方法所需的任何固定数据,以及表中已经存在的所有元组的条目。通常安布尔德
函数将调用表_索引_构建_扫描()
扫描表中现有的元组,并计算需要插入索引的键。函数必须返回包含新索引统计信息的palloc结构。
void
ambuildempty (Relation indexRelation);
构建一个空索引,并将其写入初始化fork(INIT_FORKNUM
)关于给定关系。此方法仅对未标记的索引调用;每次服务器重启时,写入初始化分支的空索引将被复制到主关系分支上。
bool
aminsert (Relation indexRelation,
Datum *values,
bool *isnull,
ItemPointer heap_tid,
Relation heapRelation,
IndexUniqueCheck checkUnique,
bool indexUnchanged,
IndexInfo *indexInfo);
在现有索引中插入新元组。这个价值观
和isnull
数组给出要索引的键值,以及堆_tid
是要编制索引的TID。如果访问方法支持唯一索引(其amcanunique
(这是真的)那么checkUnique
指示要执行的唯一性检查的类型。这取决于唯一约束是否可延迟;看见第62.5节详细信息。通常,访问方法只需要健康教育
执行唯一性检查时的参数(从那时起,它必须查看堆以验证元组的活性)。
这个指数改变
布尔值给出了有关要索引的元组的性质的提示。如果为true,则元组是索引中某个现有元组的副本。新元组是一个逻辑上没有变化的后续MVCC元组版本。这种情况发生在使现代化
不会修改索引中包含的任何列,但仍需要索引中的新版本。索引AM可能会使用此提示来决定在同一逻辑行的多个版本累积的索引部分应用自下而上的索引删除。请注意,更新非键列不会影响指数改变
.
函数的布尔结果值只有在checkUnique
是唯一检查部分
。在这种情况下,true结果意味着新条目是已知唯一的,而false意味着它可能是非唯一的(必须安排延迟的唯一性检查)。对于其他情况,建议使用恒定的假结果。
有些索引可能不会索引所有元组。如果元组不被索引,阿明塞特
应该什么都不做就回来。
如果索引AM希望在SQL语句中的连续索引插入之间缓存数据,它可以在SQL语句中分配空间indexInfo->ii_上下文
并将指向数据的指针存储在indexInfo->ii_AmCache
(最初为空)。
IndexBulkDeleteResult *
ambulkdelete (IndexVacuumInfo *info,
IndexBulkDeleteResult *stats,
IndexBulkDeleteCallback callback,
void *callback_state);
从索引中删除元组。这是一个“批量删除”操作,旨在通过扫描整个索引并检查每个条目以确定是否应该删除来实现。警察进来了回拨
必须在样式中调用函数回拨(*
工贸署*,callback_state)返回bool
,以确定是否要删除由其引用的TID标识的任何特定索引条目。必须返回NULL或palloc'd结构,其中包含有关删除操作效果的统计信息。如果不需要将任何信息传递给用户,则可以返回NULLamvacuumcleanup
.
因为有限维护工作记忆
, 安布尔克德莱特
当要删除多个元组时,可能需要多次调用。这个统计数据
参数是对该索引的上一次调用的结果(在真空
手术)。这允许AM在整个操作中累积统计信息。典型的安布尔克德莱特
将修改并返回相同的结构,如果统计数据
不是空的。
IndexBulkDeleteResult *
amvacuumcleanup (IndexVacuumInfo *info,
IndexBulkDeleteResult *stats);
打扫干净真空
操作(零或更多)安布尔克德莱特
电话)。除了返回索引统计信息之外,它不必做任何事情,但它可能会执行批量清理,例如回收空的索引页。统计数据
最后是什么安布尔克德莱特
返回呼叫,如果返回,则返回NULL安布尔克德莱特
未调用,因为不需要删除元组。如果结果不为NULL,则它必须是palloc'd结构。它包含的统计信息将用于更新pg_类
,并将由真空
如果冗长的
是的。如果索引在运行期间没有任何更改,则可以返回NULL真空
操作,但应返回正确的统计信息。
amvacuumcleanup
也将在完成分析
活动在这种情况下统计数据
始终为空,任何返回值都将被忽略。这种情况可以通过检查来区分信息->仅分析
。建议access方法在此类调用中除了插入后清理之外不做任何事情,并且仅在autovacuum worker进程中进行。
bool
amcanreturn (Relation indexRelation, int attno);
检查索引是否支持仅索引扫描在给定列上,通过返回该列的原始索引值。属性号基于1,即第一列的attno为1.如果支持,则返回true,否则返回false。对于包含的列(如果支持的话),这个函数应该总是返回true,因为包含的列中几乎没有无法检索的点。如果访问方法根本不支持仅索引扫描,则amcanreturn
领域索引路线
struct可以设置为NULL。
void
amcostestimate (PlannerInfo *root,
IndexPath *path,
double loop_count,
Cost *indexStartupCost,
Cost *indexTotalCost,
Selectivity *indexSelectivity,
double *indexCorrelation,
double *indexPages);
估计索引扫描的成本。此功能在中有详细描述第62.6节在下面
bytea *
amoptions (ArrayType *reloptions,
bool validate);
分析并验证索引的reloptions数组。仅当索引存在非空的reloptions数组时,才会调用此函数。重新选择
是一个文本
包含表单项的数组名称
=
价值
.函数应该构造一个二进制数据
值,该值将被复制到rd_选项
索引的relcache项的字段。的数据内容二进制数据
值是开放的,供访问方法定义;大多数标准访问方法都使用struct标准偏差
什么时候*验证
如果为true,则如果任何选项无法识别或具有无效值,函数应报告适当的错误消息;什么时候验证
如果为false,则应忽略无效条目。(验证
*加载已存储在中的选项时为falsepg_目录
; 只有当access方法更改了选项规则时,才能找到无效条目,在这种情况下,忽略过时条目是合适的。)如果需要默认行为,可以返回NULL。
bool
amproperty (Oid index_oid, int attno,
IndexAMProperty prop, const char *propname,
bool *res, bool *isnull);
这个安培特性
方法允许索引访问方法重写pg_索引_列_具有_属性
以及相关功能。如果访问方法对于索引属性查询没有任何特殊行为,则安培特性
领域索引路线
struct可以设置为NULL。否则安培特性
方法将被调用*索引
和阿特诺
都是零pg_indexam_具有_属性
打电话,或者索引
有效且阿特诺
零分pg_索引_具有_属性
打电话,或者索引
有效且阿特诺
大于零的pg_索引_列_具有_属性
电话。道具
是一个枚举值,用于标识正在测试的属性,而propname
是原始属性名称字符串。如果核心代码无法识别属性名称,则道具
是AMPROP_未知
.访问方法可以通过检查来定义自定义属性名称propname
为了比赛(使用)pg_strcasecmp
匹配,以与核心代码保持一致);对于核心代码已知的名称,最好进行检查道具
*.如果安培特性
方法返回符合事实的
然后确定了属性测试结果:必须设置*res
要返回或设置的布尔值*isnull
到符合事实的
返回空值。(两个引用变量都初始化为错误的
在通话前。)如果安培特性
方法返回错误的
然后,核心代码将继续其正常逻辑,以确定属性测试结果。
应该实现支持排序运算符的访问方法AMPROP_距离_可订购
属性测试,因为核心代码不知道如何做,并且将返回NULL。它也可能有利于实施AMPROP_可退货
测试,如果这比打开索引并调用amcanreturn
,这是核心代码的默认行为。默认行为应符合所有其他标准属性的要求。
char *
ambuildphasename (int64 phasenum);
返回给定生成阶段编号的文本名称。阶段号是指通过pgstat_进度_更新_参数
界面然后,阶段名称将显示在pg_统计_进度_创建_索引
看法
bool
amvalidate (Oid opclassoid);
只要access方法能够合理地验证指定运算符类的目录项。例如,这可能包括测试是否提供了所有必需的支持功能。这个amvalidate
如果opclass无效,函数必须返回false。问题应报告给电子报告
消息,通常在信息
数量
void
amadjustmembers (Oid opfamilyoid,
Oid opclassoid,
List *operators,
List *functions);
验证提议的新运算符和运算符族的功能成员,只要访问方法能够合理地做到这一点,如果默认值不令人满意,则设置它们的依赖关系类型。这叫做在创建操作符类
在ALTER运算符族添加
; 在后一种情况下*opclassoid
*是残疾人
这个列表
参数是OpFamilyMember
结构,如中所定义阿玛皮。H
.由该功能完成的测试通常是由amvalidate
自从业余会员
不能假设它看到的是一组完整的成员。例如,检查支持功能的签名是合理的,但不检查是否提供了所有必需的支持功能。任何问题都可以通过抛出错误来报告。的依赖项相关字段OpFamilyMember
结构由核心代码初始化,以便在opclass上创建硬依赖项(如果需要)创建操作符类
,或对opfamily的软依赖(如果是ALTER运算符族添加
. 业余会员
如果其他行为更合适,可以调整这些字段。例如,GIN、GiST和SP GiST总是将运算符成员设置为对opfamily具有软依赖,因为在这些索引类型中,运算符和opclass之间的连接相对较弱;因此,允许自由添加和删除操作员成员是合理的。可选的支持函数通常也被赋予软依赖项,以便在必要时可以删除它们。
当然,索引的目的是支持对匹配可索引元素的元组进行扫描哪里
状态,常被称为合格者或扫描键索引扫描的语义将在第62.3节在下面索引访问方法可以支持“普通”索引扫描、“位图”索引扫描,或者两者都支持。索引访问方法必须或可能提供的扫描相关功能包括:
IndexScanDesc
ambeginscan (Relation indexRelation,
int nkeys,
int norderbys);
准备索引扫描。这个肯基
和诺德比
参数表示将在扫描中使用的Qual和排序运算符的数量;这些可能有助于空间分配。请注意,尚未提供扫描键的实际值。结果必须是一个palloc'd结构。出于实现原因,索引访问方法必须通过调用RelationGetIndexScan()
.在大多数情况下安贝金斯坎
除了打那个电话,或者获取锁之外,几乎没有什么作用;索引扫描启动的有趣部分在阿姆雷斯坎
.
void
amrescan (IndexScanDesc scan,
ScanKey keys,
int nkeys,
ScanKey orderbys,
int norderbys);
启动或重新启动索引扫描,可能使用新的扫描键。(要使用以前传递的键重新启动,将为钥匙
和/或订货人
)注意,操作员的钥匙或订单数量不允许大于传递给的数量安贝金斯坎
。在实践中,当嵌套循环联接选择了新的外部元组,因此需要一个新的键比较值时,会使用重新启动功能,但扫描键结构保持不变。
bool
amgettuple (IndexScanDesc scan,
ScanDirection direction);
获取给定扫描中的下一个元组,沿给定方向移动(在索引中向前或向后)。如果获得了元组,则返回true;如果没有匹配的元组,则返回false。在真实情况下,元组TID存储在扫描
结构请注意,“成功”只意味着索引包含与扫描键匹配的条目,而不是元组必须仍然存在于堆中,或者将通过调用方的快照测试。关于成功,amgettuple
还必须设置扫描->X_重新检查
对或错。False表示确定索引项与扫描键匹配。True表示这是不确定的,在获取堆元组后,必须根据堆元组重新检查扫描键表示的条件。该条款支持“有损”索引运算符。请注意,重新检查只会扩展到扫描条件;部分索引谓词(如果有)永远不会被amgettuple
来电者。
如果索引支持仅索引扫描(即。,amcanreturn
对于其任何列,返回true),则成功后AM还必须进行检查扫描->xs_want_itup
,如果这是真的,它必须返回索引项的原始索引数据。哪一列amcanreturn
返回false可以作为null返回。数据可以以索引
指针存储在扫描->xs_itup
,具有元组描述符扫描->xs_itupdesc
; 或者以一堆
指针存储在扫描->xs_启动
,具有元组描述符扫描->xs_hitupdesc
(在重建可能不适合某个应用程序的数据时,应使用后一种格式。)索引
)在任何一种情况下,指针引用的数据的管理都是访问方法的责任。数据必须保持良好状态,至少要等到下一个月amgettuple
, 阿姆雷斯坎
或阿蒙德斯卡纳
打电话进行扫描。
这个amgettuple
仅当访问方法支持“普通”索引扫描时,才需要提供函数。如果没有,那么amgettuple
领域索引路线
struct必须设置为NULL。
int64
amgetbitmap (IndexScanDesc scan,
TIDBitmap *tbm);
获取给定扫描中的所有元组,并将它们添加到提供的调用方TIDBitmap
(也就是说,将元组ID集合放入位图中已有的任何集合中)。返回获取的元组数(这可能只是一个近似计数,例如,一些AMs没有检测到重复的元组)。在位图中插入元组ID时,amgetbitmap
可以指示特定元组ID需要重新检查扫描条件。这类似于重新检查
输出参数amgettuple
.注意:在当前的实现中,对该功能的支持与对位图本身有损存储的支持混为一谈,因此调用者会重新检查扫描条件和部分索引谓词(如果有)以获得可重新检查的元组。然而,这可能并不总是正确的。amgetbitmap
和amgettuple
不能在同一索引扫描中使用;使用时还有其他限制amgetbitmap
,如中所述第62.3节.
这个amgetbitmap
仅当访问方法支持“位图”索引扫描时,才需要提供函数。如果没有,那么amgetbitmap
领域索引路线
struct必须设置为NULL。
void
amendscan (IndexScanDesc scan);
结束扫描并释放资源。这个扫描
结构本身不应被释放,但必须释放访问方法在内部获取的任何锁或管脚,以及由访问方法分配的任何其他内存安贝金斯坎
以及其他与扫描相关的功能。
void
ammarkpos (IndexScanDesc scan);
标记当前扫描位置。访问方法每次扫描只需支持一个记忆的扫描位置。
这个安马尔克斯堡
仅当访问方法支持有序扫描时,才需要提供函数。如果没有,那么安马尔克斯堡
领域索引路线
struct可以设置为NULL。
void
amrestrpos (IndexScanDesc scan);
将扫描恢复到最近标记的位置。
这个阿姆斯特罗斯酒店
仅当访问方法支持有序扫描时,才需要提供函数。如果没有,那么阿姆斯特罗斯酒店
领域索引路线
struct可以设置为NULL。
除了支持普通索引扫描外,某些类型的索引可能希望支持并行索引扫描,允许多个后端协同执行索引扫描。索引访问方法应该进行安排,以便每个协作进程返回元组的子集,该子集将由普通的非并行索引扫描执行,但这些子集的并集等于普通的非并行索引扫描返回的元组集。此外,虽然并行扫描返回的元组不需要任何全局排序,但在每个协作后端中返回的元组子集的排序必须与请求的排序匹配。可以实现以下功能以支持并行索引扫描:
Size
amestimateparallelscan (void);
估计并返回访问方法执行并行扫描所需的动态共享内存字节数。(这个数字是对AM独立数据所需空间量的补充,而不是替代。)ParallelIndexScanDescData
.)
对于不支持并行扫描或所需额外存储字节数为零的访问方法,无需实现此功能。
void
aminitparallelscan (void *target);
在并行扫描开始时,将调用此函数初始化动态共享内存。*目标
*将至少指向以前由返回的字节数A估计并行扫描
,此函数可以使用该空间量存储它想要的任何数据。
对于不支持并行扫描的访问方法,或者在所需共享内存空间不需要初始化的情况下,无需实现此功能。
void
amparallelrescan (IndexScanDesc scan);
如果实现了该函数,则在必须重新启动并行索引扫描时将调用该函数。它应该重置由设置的任何共享状态平行扫描
这样就可以从头开始扫描。