Table of Contents
索引是增强数据库性能的一种常见方式。索引允许数据库服务器比没有索引时更快地找到并检索特定行。但索引也会给整个数据库系统带来额外开销,因此应当合理使用。
假设我们有一个类似如下的表:
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命令来更新统计信息,以便查询规划器作出更有根据的决策。关于如何判断某个索引是否被使用,以及规划器何时和为何可能选择不使用索引,可参见Chapter 14。
索引还可以让带有搜索条件的UPDATE和DELETE命令受益。索引也可以用于连接搜索。因此,定义在连接条件组成列上的索引也能显著加速带连接的查询。
一般来说,PostgreSQL索引可用于优化包含一个或多个如下形式WHERE或JOIN子句的查询:
indexed-columnindexable-operatorcomparison-value
其中,indexed-column是索引所定义在其上的列或表达式。indexable-operator是该索引针对该列所用操作符类中的一个操作符(下文会进一步说明)。而comparison-value可以是任何非易失且不引用索引所属表的表达式。
在某些情况下,查询规划器可以从其他 SQL 构造中提取出这种形式的可索引子句。一个简单示例是,如果原始子句是
comparison-valueoperatorindexed-column
那么如果原始operator有一个可交换操作符,并且该操作符属于该索引的操作符类,就可以把它翻转成可索引的形式。
在大表上创建索引可能需要很长时间。默认情况下,PostgreSQL允许在创建索引期间并行执行读取(SELECT语句),但写入(INSERT、UPDATE、DELETE)会被阻塞,直到索引构建完成。在生产环境中,这往往不可接受。可以允许在创建索引时并行写入,但有若干注意事项需要了解,详见Building Indexes Concurrently。
索引创建之后,系统还必须使其与表保持同步。这会给数据操作增加开销。索引还可能阻止创建堆内元组。因此,那些在查询中很少使用或从不使用的索引应当被移除。
如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。