51.1. 索引的系统表记录

每个索引访问方法都在系统表pg_am里面用 一行来描述(参阅Section 45.3)。一个 pg_proc 行的主要内容是引用pg_proc里面的记录,用来标识索引访问方法提供的索引 访问函数。这些函数的接口(API)在本章后面描述。另外,pg_am的数据行生命了几个索引访问方法的固定属性,比如,它是否 支持多字段索引。目前还没有创建、删除pg_am 记录的特殊支持;任何想写这么一个新的访问方法的人都需要能够自己向这个 表里面插入合适的新行。

要想有真正用处,一个索引访问方法还必须有一个或多个 操作符类,定义在pg_opclass,pg_amop,pg_amproc 里面。这些记录允许规划器判断哪些查 询的条件可以适用于用这个索引访问方法创建的索引。操作符类在Section 35.14里面定义,是读取本章的前提之一。

一个独立的索引是由一行pg_class记录以物理关系的方式描述的,加上一个 pg_index行,表示该索引的逻辑内容 —也就是说,它所拥有的索引字段集,以 及被相关的操作符类捕获的这些字段的语义。索引字段(键值)可以是下层表的 字段,也可以是该表的数据哈工上的表达式。索引访问方法通常不关心索引的 键值来自何妨(它总是操作预处理完毕的键值),但是它会对 pg_index 里面的操作符类信息很感兴趣。所有这些表记录都可 以当作(Relation)数据结构的一部分访问,这个数据结构会在 对该索引的所有操作上都传递到对应的函数中。

pg_am 中的有些标志字段的含义并不那么直观。 amcanunique 的需求在Section 51.5里讨论过, amcanmulticol标志断言该索引访问方法支持多字段索引, amoptionalkey 断言它允许对那种在第一个索引 字段上没有给出可索引限制子句的扫描。如果 amcanmulticol为假,那么 amoptionalkey实际 上说的是该访问方法是否允许不带限制子句的全索引扫描。 那些支持多字段索引的访问访法必须支持那些在省略了除第一个字段以外的其它 字段的约束的扫描;不过,系统允许这些访问访法要求在第一个字段上出现一些 限制,这一点是通过把amoptionalkey设置为假 来实现的。amindexnulls断言该索引记录是为 NULL键值创建的。 因为大多数可以索引的操作符都是严格的,因此不能对NULL输入返回TRUE, 所以,第一眼看见会觉得不为NULL存储索引记录的想法很吸引人:因为他们不 可能被一个索引扫描返回。不过,这个想法在一个给出的索引字段上没有限制子 句的索引扫描的情况下就不行了;这样的扫描应该包括NULL行。实际上,这意 味着设置了amoptionalkey为真的索引必须索引 NULL,因为规划器可能会决定在根本没有扫描键字的时候使用这样的索引。这 样的索引必须可以在完全没有扫描键字的情况下运行。另外一个限制是一个支持 多字段索引的索引访问方法必须支持第一个字段后面的字段的NULL的索引,因 为规划器会认为这个索引可以用于那些没有限制这些字段的查询。比如,假设有 个索引在(a,b)上,而一个查询的条件是WHERE a = 4。 系统会认为这个索引可以用于扫描 a = 4的数据行, 如果索引忽略了 b 为空的数据行,那么就是错误的。不过,如果第一个索引字段 值是空,那么忽略它是 OK 的。因此,只是在索引访问方法索引了所有行,包括 任意NULL的组合,之后,amindexnulls才可以 设置为真值。 指向amindexnulls的一个变址存取方法 也会指向amsearchnulls,这表示它支持设置 为空不为空子句为搜索条件。