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 章。
索引还可以使带有搜索条件的UPDATE
和DELETE
命令受益。此外,索引还可用于联接搜索中。因此,在联接条件的一部分的列上定义的索引还可以显著加快带有联接的查询。
通常,PostgreSQL索引可用于优化包含一个或多个形式为WHERE
或JOIN
子句的查询
indexed-column indexable-operator comparison-value
在此处,indexed-column
是已为其定义索引的列或表达式。indexable-operator
是索引列的索引操作符类的成员的操作符。(有关此内容的更多详细信息请参见下文。)并且*comparison-value
*可以是任何非易失且不引用索引表的表达式。
在某些情况下,查询计划程序可以从另一个 SQL 结构中提取此形式的可索引子句。一个简单的示例是,如果原始子句为
comparison-value operator indexed-column
然后,如果原始*operator
*具有属于索引运算符类的换向运算符,则可以将其翻转为可索引形式。
在大型表上创建索引可能需要很长时间。默认情况下,PostgreSQL允许在表上并行执行读取(SELECT
语句)和索引创建,但写入(INSERT
、UPDATE
、DELETE
)在索引构建完成之前会被阻塞。在生产环境中,这通常是不可接受的。可以允许写入与索引创建并行进行,但需要注意一些注意事项——有关详细信息,请参见同时构建索引。
在创建索引后,系统必须使其与表保持同步。这会增加数据操作操作的开销。索引还可以防止创建堆专用元组。因此,应删除在查询中很少或从未使用的索引。