2025年9月25日: PostgreSQL 18 发布!
支持的版本: 当前 (18) / 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

11.1. 引言 #

假设我们有一个如下的表

CREATE TABLE test1 (
    id integer,
    content varchar
);

并且应用程序发出许多如下形式的查询

SELECT content FROM test1 WHERE id = constant;

在没有任何预先准备的情况下,系统将不得不逐行扫描整个test1表,以查找所有匹配的条目。如果test1表中有许多行,而这样的查询只返回少数几行(可能为零或一行),那么这显然是一种效率不高的方法。但是,如果系统已被指示在id列上维护一个索引,它就可以使用一种更有效的方法来定位匹配的行。例如,它可能只需要深入搜索树的几层。

大多数非虚构类书籍也采用了类似的方法:读者经常查找的术语和概念被收集在书末的字母索引中。感兴趣的读者可以相对快速地浏览索引并翻到相应的页面,而不是阅读整本书来查找感兴趣的内容。正如作者的任务是预见读者可能查找的条目一样,数据库程序员的任务也是预见哪些索引会有用。

如下命令可以用来在id列上创建索引,如前所述

CREATE INDEX test1_id_index ON test1 (id);

索引名 test1_id_index 可以自由选择,但您应该选择一个能够让您以后记住该索引用途的名称。

要删除索引,请使用DROP INDEX命令。索引可以随时添加到表上或从表中删除。

一旦创建了索引,就不需要进一步的干预了:当表被修改时,系统会自动更新索引,并且当它认为使用索引比顺序表扫描更有效时,它会在查询中使用该索引。但是,您可能需要定期运行ANALYZE命令来更新统计信息,以便查询规划器能够做出明智的决策。有关如何确定索引是否被使用以及规划器何时以及为何可能选择使用索引的信息,请参阅第 14 章

索引也可以为具有搜索条件的UPDATEDELETE命令提供帮助。此外,索引也可以用于连接搜索。因此,在连接条件列上定义的索引也可以显著加快带有连接的查询速度。

总的来说,PostgreSQL索引可用于优化包含一个或多个如下形式的WHEREJOIN子句的查询

indexed-column indexable-operator comparison-value

其中,indexed-column是索引定义的任何列或表达式。indexable-operator是索引对于被索引列的操作符类的成员操作符。(更多细节将在后面介绍。)而comparison-value可以是任何非易失性且不引用索引表的表达式。

在某些情况下,查询规划器可以从另一个SQL构造中提取出这种形式的可索引子句。一个简单的例子是,如果原始子句是

comparison-value operator indexed-column

那么,如果原始operator有一个换位操作符,并且该操作符是索引的操作符类中的一个成员,则可以将其反转为可索引的形式。

在大型表上创建索引可能需要很长时间。默认情况下,PostgreSQL允许在创建索引的同时对表进行读取(SELECT语句),但写入(INSERTUPDATEDELETE)将被阻塞,直到索引构建完成。在生产环境中,这通常是不可接受的。可以允许在创建索引的同时进行写入操作,但需要注意几个注意事项——有关更多信息,请参阅并发构建索引

创建索引后,系统必须将其与表保持同步。这会增加数据操作操作的开销。索引也可能阻止仅堆元组 (HOT)的创建。因此,在查询中很少或从不使用的索引应该被删除。

提交更正

如果您在文档中看到任何不正确、与您对特定功能的体验不符或需要进一步说明的内容,请使用此表单报告文档问题。