支持的版本:当前 (17) / 16 / 15 / 14 / 13
开发版本:devel
不支持的版本:12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1

62.3. 索引扫描 #

在索引扫描中,索引访问方法负责返回所有它被告知的、与扫描键匹配的元组的 TID。访问方法参与实际从索引的父表中获取这些元组,也不参与确定它们是否通过扫描的可见性测试或其他条件。

扫描键是 WHERE 子句的内部表示,其形式为 index_key operator constant,其中索引键是索引的列之一,运算符是与该索引列关联的运算符族的成员之一。索引扫描具有零个或多个扫描键,这些扫描键隐式地进行 AND 运算 — 返回的元组应满足所有指示的条件。

访问方法可以报告索引对于特定查询是有损的,或者需要重新检查。这意味着索引扫描将返回所有通过扫描键的条目,以及可能不通过扫描键的其他条目。核心系统的索引扫描机制将再次将索引条件应用于堆元组,以验证是否真的应该选择它。如果未指定重新检查选项,则索引扫描必须返回完全匹配的条目集。

请注意,确保它正确地找到所有通过所有给定扫描键的条目完全取决于访问方法。此外,核心系统将简单地移交所有与索引键和运算符族匹配的 WHERE 子句,而不会进行任何语义分析以确定它们是否冗余或矛盾。例如,给定 WHERE x > 4 AND x > 14,其中 x 是一个 b 树索引列,则由 b 树的 amrescan 函数来识别第一个扫描键是冗余的并且可以丢弃。amrescan 期间需要的预处理程度取决于索引访问方法需要将扫描键简化为 规范化 形式的程度。

一些访问方法以明确定义的顺序返回索引条目,而另一些则不然。实际上,访问方法支持排序输出的方式有两种:

  • 始终以其数据的自然顺序(例如 btree)返回条目的访问方法应将 amcanorder 设置为 true。目前,此类访问方法必须为其相等和排序运算符使用与 btree 兼容的策略编号。

  • 支持排序运算符的访问方法应将 amcanorderbyop 设置为 true。这表明索引能够以满足 ORDER BY index_key operator constant 的顺序返回条目。该形式的扫描修饰符可以像前面描述的那样传递给 amrescan

amgettuple 函数有一个 direction 参数,它可以是 ForwardScanDirection(正常情况)或 BackwardScanDirection。如果 amrescan 之后的第一次调用指定了 BackwardScanDirection,则匹配的索引条目集将从后向前扫描,而不是正常的从前向后的方向,因此 amgettuple 必须返回索引中的最后一个匹配元组,而不是像通常情况下的第一个匹配元组。(这只会发生在将 amcanorder 设置为 true 的访问方法上。)在第一次调用之后,amgettuple 必须准备好从最近返回的条目开始在任一方向上推进扫描。(但是,如果 amcanbackward 为 false,则所有后续调用都将与第一次调用具有相同的方向。)

支持有序扫描的访问方法必须支持在扫描中标记位置,并在以后返回到标记的位置。同一位置可能会被恢复多次。但是,每个扫描只需要记住一个位置;新的 ammarkpos 调用会覆盖先前标记的位置。不支持有序扫描的访问方法无需在 IndexAmRoutine 中提供 ammarkposamrestrpos 函数;将这些指针设置为 NULL 即可。

扫描位置和标记位置(如果有)都必须在索引中并发插入或删除的情况下保持一致。如果在扫描开始时存在,扫描会找到新插入的条目,或者在重新扫描或备份时,即使第一次没有返回,扫描也会返回此类条目,这是可以的。类似地,并发删除可能会或可能不会反映在扫描结果中。重要的是,插入或删除不会导致扫描遗漏或多次返回本身未被插入或删除的条目。

如果索引存储原始索引的数据值(而不是它们的一些有损表示),则支持仅索引扫描,其中索引返回实际数据,而不仅仅是堆元组的 TID,这很有用。如果可见性映射显示 TID 位于所有可见页面上,则这将仅避免 I/O;否则,仍必须访问堆元组以检查 MVCC 可见性。但这与访问方法无关。

可以使用 amgetbitmap 来代替 amgettuple 来执行索引扫描,以便一次获取所有元组。这可能比 amgettuple 明显更有效,因为它允许避免访问方法中的锁定/解锁循环。原则上,amgetbitmap 的效果应与重复的 amgettuple 调用相同,但我们施加了一些限制以简化事情。首先,amgetbitmap 一次返回所有元组,并且不支持标记或恢复扫描位置。其次,元组以不具有任何特定顺序的位图形式返回,这就是 amgetbitmap 不采用 direction 参数的原因。(排序运算符也不会为此类扫描提供。)此外,使用 amgetbitmap 没有仅索引扫描的规定,因为无法返回索引元组的内容。最后,amgetbitmap 不保证返回的元组的任何锁定,其含义在第 62.4 节中进行了阐述。

请注意,如果访问方法的内部实现不适合一个 API 或另一个 API,则允许访问方法仅实现 amgetbitmap 而不实现 amgettuple,反之亦然。

提交更正

如果您在文档中发现任何不正确、与您使用特定功能的经验不符或需要进一步澄清的内容,请使用此表格来报告文档问题。