11.1. 简介

假设我们有一个如下的表:

CREATE TABLE test1 (
    id integer,
    content varchar
);

而应用发出很多以下形式的查询:

SELECT content FROM test1 WHERE id = constant;

在没有事前准备的情况下,系统不得不扫描整个test1表,一行一行地去找到所有匹配的项。如果test1中有很多行但是只有一小部分行(可能是0或者1)需要被该查询返回,这显然是一种低效的方式。但是如果系统被指示维护一个在id列上的索引,它就能使用一种更有效的方式来定位匹配行。例如,它可能仅仅需要遍历一棵搜索树的几层而已。

类似的方法也被用于大部分非小说书籍中:经常被读者查找的术语和概念被收集在一个字母序索引中放在书籍的末尾。感兴趣的读者可以相对快地扫描索引并跳到合适的页而不需要阅读整本书来寻找感兴趣的材料。正如作者的任务是准备好读者可能会查找的术语一样,数据库程序员也需要预见哪些索引会有用。

正如前面讨论的,下列命令可以用来在id列上创建一个索引:

CREATE INDEX test1_id_index ON test1 (id);

索引的名字test1_id_index可以自由选择,但我们最好选择一个能让我们想起该索引用途的名字。

为了移除一个索引,可以使用DROP INDEX命令。索引可以随时被创建或删除。

一旦一个索引被创建,就不再需要进一步的干预:系统会在表更新时更新索引,而且会在它觉得使用索引比顺序扫描表效率更高时使用索引。但我们可能需要定期地运行ANALYZE命令来更新统计信息以便查询规划器能做出正确的决定。通过第 14 章的信息可以了解如何找出一个索引是否被使用以及规划器在何时以及为什么会选择使用索引。

索引也会使带有搜索条件的UPDATEDELETE命令受益。此外索引还可以在连接搜索中使用。因此,一个定义在连接条件列上的索引可以显著地提高连接查询的速度。

在一个大表上创建一个索引会耗费很长的时间。默认情况下,PostgreSQL允许在索引创建时并行地进行读(SELECT命令),但写(INSERTUPDATEDELETE)则会被阻塞直到索引创建完成。在生产环境中这通常是不可接受的。在创建索引时允许并行的写是可能的,但是有些警告需要注意,更多信息可以参考Building Indexes Concurrently

一个索引被创建后,系统必须保持它与表同步。这增加了数据操作的负担。因此哪些很少或从不在查询中使用的索引应该被移除。