假设我们有一个如下的表:
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 章的信息可以了解如何找出一个索引是否被使用以及规划器在何时以及为什么会选择不使用索引。
索引也会对带有搜索条件的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
)则会被阻塞直到索引创建完成。在生产环境中这通常是不可接受的。在创建索引时允许并行的写是可能的,但是有些警告需要注意,更多信息可以参考Building Indexes Concurrently。
创建索引后,系统必须将其与表同步。这会增加数据操作的开销。索引还可以阻止创建 仅存储元组。因此,很少或从不在查询中使用的索引 应该被移除。