选择 打开 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0
历史版本PostgreSQL 9.5 已于 2021 年 2 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本

第 58 章 索引访问方法接口定义

本章定义 PostgreSQL 核心系统与管理各个索引类型的索引访问方法之间的接口。除这里规定的内容之外,核心系统对索引一无所知,因此可以通过编写附加代码来开发全新的索引类型。

PostgreSQL 中所有索引在技术上都称为二级索引;也就是说,索引与它所描述的表文件在物理上是分离的。每个索引都存储为独立的物理关系,因此在 pg_class 目录中都有一个条目。索引的内容完全由其索引访问方法控制。实践中,所有索引访问方法都会把索引划分为标准大小的页面,以便使用常规的存储管理器和缓冲区管理器访问索引内容。(现有的所有索引访问方法还都使用 第 63.6 节 中描述的标准页面布局,而且它们都对索引元组头使用相同的格式;但这些决定并不是访问方法必须遵循的。)

索引本质上是从一些数据键值到行版本(元组)在索引父表中的元组标识符TIDs)的映射。一个 TID 由块号以及该块中的项号组成(见 第 63.6 节)。这些信息足以从表中取出某个特定的行版本。索引并不直接知道在 MVCC 之下同一逻辑行可能会存在多个现存版本;对索引来说,每个元组都是一个独立对象,需要它自己的索引条目。因此,对一行的更新总会为该行创建全新的索引条目,即使键值并未改变也是如此。(HOT 元组是这一说法的例外;但索引同样不直接处理它们。)当死元组自身被回收时(通过清理),它们对应的索引条目也会被回收。

58.1. 索引的目录条目 #

每种索引访问方法都由系统目录 pg_am 中的一行描述(参见 第 49.3 节)。pg_am 行的主要内容是一些指向 pg_proc 条目的引用,它们标识了该访问方法所提供的索引访问函数。这些函数的 API 将在本章后面定义。此外,pg_am 行还指定了访问方法的一些固定属性,例如它是否支持多列索引。目前没有任何专门用于创建或删除 pg_am 条目的支持;能够编写新访问方法的人,理应有能力自己插入合适的行。

要使一种索引访问方法真正可用,还必须在 pg_opfamilypg_opclasspg_amoppg_amproc 中定义一个或多个操作符族操作符类。这些条目使规划器能够确定该访问方法的索引可以使用哪些查询限定条件。关于操作符族和操作符类的说明见 第 35.14 节;阅读本章前应先掌握这些内容。

单个索引由两个系统目录条目共同定义:一个 pg_class 条目把它描述为一个物理关系,另一个 pg_index 条目给出索引的逻辑内容,也就是它包含哪些索引列,以及由相关操作符类定义的这些列的语义。索引列(键值)既可以是底层表的简单列,也可以是基于表行的表达式。索引访问方法通常并不关心索引键值来自何处(它拿到的总是预先计算好的键值),但会非常关心 pg_index 中的操作符类信息。这两个目录条目都可以作为传递给索引上所有操作的 Relation 数据结构的一部分来访问。

pg_am 的某些标志列还有一些不那么直观的含义。amcanunique 的要求见 第 58.5 节amcanmulticol 标志表明该访问方法支持多列索引,而 amoptionalkey 表明它允许在第一索引列上没有给出可索引限制子句时进行扫描。当 amcanmulticol 为假时,amoptionalkey 实质上表示该访问方法是否支持没有任何限制子句的全索引扫描。支持多个索引列的访问方法必须支持在第一列之后省略任意一个或全部列限制条件的扫描;但它们可以要求第一索引列必须出现某种限制条件,这通过把 amoptionalkey 设为假来表示。索引 AM 可能把 amoptionalkey 设为假的一个原因,是它不索引 NULL 值。由于大多数可索引操作符都是严格的(strict),因此对 NULL 输入不可能返回 true,所以乍看之下不存储 NULL 值的索引条目似乎很有吸引力:无论如何,这些条目似乎都不可能被索引扫描返回。然而,当某个索引扫描对给定索引列没有限制子句时,这个论证就不成立了。实践中这意味着,若索引把 amoptionalkey 设为真,就必须索引 NULL 值,因为规划器可能决定在完全没有扫描键的情况下使用这种索引。与此相关的另一个限制是,支持多个索引列的索引访问方法必须支持对第一列之后各列中的 NULL 值建立索引,因为规划器会假定该索引可用于不限制这些列的查询。例如,考虑一个在 (a,b) 上的索引以及查询 WHERE a = 4。系统会假定该索引可用于扫描满足 a = 4 的行;如果索引省略了 b 为 NULL 的行,这个假定就是错误的。不过,省略第一索引列为 NULL 的行是可以的。对 NULL 值建立索引的索引访问方法还可以设置 amsearchnulls,表示它支持把 IS NULLIS NOT NULL 子句作为搜索条件。

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。