假设我们有一个类似于此的表
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
)将被阻止,直到索引构建完成。在生产环境中,这种情况通常是不可接受的。可以在与创建索引同时并行进行写入,但需要注意几个注意事项 — 有关更多信息,请参见同时构建索引。
在创建索引后,系统必须保持它与表的同步。这增加了数据操作开销。索引还可以防止创建只堆元组。因此应该移除很少甚至从未在查询中使用过的索引。