# 创建索引

CREATE INDEX — 定义一个新索引

# 概要

CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] name ] ON [ ONLY ] table_name [ USING method ]
    ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass [ ( opclass_parameter = value [, ... ] ) ] ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] )
    [ INCLUDE ( column_name [, ...] ) ]
    [ WITH ( storage_parameter [= value] [, ... ] ) ]
    [ TABLESPACE tablespace_name ]
    [ WHERE predicate ]

# 描述

创建索引在指定关系的指定列上构造索引,可以是表或物化视图。索引主要用于提高数据库性能(尽管使用不当会导致性能下降)。

索引的关键字段被指定为列名,或者被指定为括号中的表达式。如果索引方法支持多列索引,则可以指定多个字段。

索引字段可以是根据表格行的一个或多个列的值计算的表达式。此功能可用于基于基础数据的一些转换来获得对数据的快速访问。例如,在上(上)将允许该条款WHERE 上(col) = 'JIM'使用索引。

PostgreSQL 提供了索引方法 B-tree、hash、GiST、SP-GiST、GIN 和 BRIN。用户也可以定义自己的索引方法,但这相当复杂。

当。。。的时候在哪里子句存在,a部分索引被建造。部分索引是只包含表的一部分的条目的索引,通常是比表的其余部分对索引更有用的部分。例如,如果您的表同时包含已开票和未开票的订单,其中未开票的订单占整个表的一小部分,但这是一个经常使用的部分,您可以通过仅在该部分上创建索引来提高性能。另一个可能的应用是使用在哪里独特对表的子集强制唯一性。看第 11.8 节进行更多讨论。

中使用的表达式在哪里子句只能引用基础表的列,但它可以使用所有列,而不仅仅是被索引的列。目前,子查询和聚合表达式也被禁止在哪里.相同的限制适用于作为表达式的索引字段。

索引定义中使用的所有函数和运算符都必须是“不可变的”,也就是说,它们的结果必须仅取决于它们的参数,而不能取决于任何外部影响(例如另一个表的内容或当前时间)。此限制确保索引的行为是明确定义的。在索引表达式中使用用户定义的函数或在哪里子句,请记住在创建函数时将其标记为不可变。

# 参数

独特

使系统在创建索引时(如果数据已存在)和每次添加数据时检查表中的重复值。尝试插入或更新会导致重复条目的数据将产生错误。

将唯一索引应用于分区表时会应用其他限制;看创建表.

同时

使用此选项时,PostgreSQL 将构建索引而不使用任何阻止并发插入、更新或删除表的锁;而标准索引构建会锁定表上的写入(但不读取),直到完成为止。使用此选项时需要注意几个注意事项 - 请参阅同时建立索引以下。

对于临时表,创建索引总是非并发的,因为没有其他会话可以访问它们,并且非并发索引创建更便宜。

如果不存在

如果已存在同名关系,则不要抛出错误。在这种情况下发出通知。请注意,不能保证现有索引与已创建的索引相同。索引名称是必需的如果不存在被指定。

包括

可选的包括子句指定将包含在索引中的列列表非关键列。非键列不能用于索引扫描搜索限定,并且出于索引强制执行的任何唯一性或排除约束的目的而忽略它。但是,仅索引扫描可以返回非键列的内容,而不必访问索引的表,因为它们可以直接从索引条目中获得。因此,添加非键列允许将仅索引扫描用于无法使用它们的查询。

将非键列添加到索引,尤其是宽列时要保守一些。如果索引元组超过索引类型允许的最大大小,数据插入将失败。在任何情况下,非键列都会复制索引表中的数据并增大索引的大小,从而可能会减慢搜索速度。此外,B-tree 重复数据删除永远不会与具有非键列的索引一起使用。

列中列出的列包括子句不需要适当的运算符类;该子句可以包括其数据类型没有为给定访问方法定义的运算符类的列。

不支持将表达式作为包含列,因为它们不能用于仅索引扫描。

目前,B-tree、GiST 和 SP-GiST 索引访问方法都支持此功能。在这些索引中,列中列出的值包括子句包含在对应于堆元组的叶元组中,但不包含在用于树导航的上层索引条目中。

姓名

要创建的索引的名称。此处不能包含模式名称;索引始终在与其父表相同的架构中创建。如果名称被省略,PostgreSQL 会根据父表的名称和索引列名称选择一个合适的名称。

只要

如果表是分区的,则表示不递归创建分区上的索引。默认为递归。

表名

要索引的表的名称(可能是模式限定的)。

方法

要使用的索引方法的名称。选择是btree,哈希,要旨,专家组,杜松子酒, 和布林.默认方法是btree.

列名

表的列的名称。

表达

基于表的一个或多个列的表达式。表达式通常必须用括号括起来,如语法所示。但是,如果表达式具有函数调用的形式,则可以省略括号。

整理

用于索引的排序规则的名称。默认情况下,索引使用为要索引的列声明的排序规则或要索引的表达式的结果排序规则。具有非默认排序规则的索引对于涉及使用非默认排序规则的表达式的查询很有用。

操作类

运算符类的名称。详情见下文。

opclass_parameter

运算符类参数的名称。详情见下文。

ASC

指定升序排序(这是默认值)。

DESC

指定降序排序。

NULLS FIRST

指定空值在非空值之前排序。这是默认情况下DESC被指定。

NULLS LAST

指定空值在非空值之后排序。这是默认情况下DESC未指定。

存储参数

特定于索引方法的存储参数的名称。看索引存储参数详情如下。

表空间名称

在其中创建索引的表空间。如果没有指定,默认_表空间被咨询,或温度_表空间用于临时表的索引。

谓词

部分索引的约束表达式。

# 索引存储参数

可选的条款规定存储参数为索引。每个索引方法都有自己的一组允许的存储参数。B-tree、hash、GiST 和 SP-GiST 索引方法都接受这个参数:

填充因子(整数)

索引的填充因子是一个百分比,它确定索引方法将尝试打包索引页面的填充程度。对于 B 树,在初始索引构建期间以及在右侧扩展索引(添加新的最大键值)时,叶页被填充到这个百分比。如果页面随后变得完全填满,它们将被拆分,从而导致磁盘索引结构碎片化。B 树使用 90 的默认填充因子,但可以选择 10 到 100 之间的任何整数值。

预期有许多插入和/或更新的表上的 B 树索引可以受益于较低的填充因子设置创建索引时间(在批量加载到表中之后)。50 - 90 范围内的值可以有效地“平滑”速度在 B-tree 索引的早期生命周期中的页面拆分次数(像这样降低填充因子甚至可能会降低页面拆分的绝对数量,尽管这种效果高度依赖于工作负载)。B-tree 自下而上的索引删除技术第 64.4.2 节依赖于页面上有一些“额外”空间来存储“额外”元组版本,因此可能会受到填充因子的影响(尽管效果通常不显着)。

在其他特定情况下,将填充因子增加到 100 可能很有用创建索引时间作为最大化空间利用的一种方式。只有当您完全确定表是静态的(即它永远不会受到插入或更新的影响)时,您才应该考虑这一点。填充因子设置为 100 否则有风险伤害性能:即使是一些更新或插入也会导致页面拆分突然泛滥。

其他索引方法以不同但大致相似的方式使用填充因子;默认填充因子因方法而异。

B-tree 索引还接受这个参数:

去重项目(布尔值)

控制 B 树重复数据删除技术的使用第 64.4.3 节.调成要么离开启用或禁用优化。(的替代拼写离开允许如中所述第 20.1 节.) 默认为.

# 笔记

车削去重项目通过关闭更改索引防止将来的插入触发重复数据删除,但本身并不使现有的发布列表元组使用标准元组表示。

GiST 索引还接受此参数:

缓冲(枚举)

确定是否使用中描述的缓冲构建技术第 65.4.1 节用于构建索引。和离开缓冲被禁用,与它已启用,并且汽车它最初是禁用的,但是一旦索引大小达到,它就会即时打开有效的_缓存_尺寸.默认是汽车.请注意,如果排序构建是可能的,它将被使用而不是缓冲构建,除非缓冲=开被指定。

GIN 索引接受不同的参数:

快速更新(布尔值)

此设置控制中描述的快速更新技术的使用第 67.4.1 节.它是一个布尔参数:实现快速更新,离开禁用它。默认是.

# 笔记

车削快速更新通过关闭更改索引防止将来的插入进入挂起的索引条目列表,但本身不会刷新以前的条目。你可能想要真空桌子或电话gin_clean_pending_list之后运行以确保清空待处理列表。

gin_pending_list_limit(整数)

风俗杜松子酒_待办的_列表_限制范围。此值以千字节为单位指定。

BRIN 索引接受不同的参数:

pages_per_range(整数)

为 BRIN 索引的每个条目定义组成一个块范围的表块的数量(请参阅第 68.1 节更多细节)。默认是128.

自动总结(布尔值)

定义每当在下一个页面上检测到插入时,是否为上一个页面范围调用摘要运行。

# 同时建立索引

创建索引可能会干扰数据库的常规操作。通常 PostgreSQL 会锁定要索引的表以防止写入,并通过对表的单次扫描来执行整个索引构建。其他事务仍然可以读取该表,但如果它们尝试插入、更新或删除表中的行,它们将阻塞,直到索引构建完成。如果系统是实时生产数据库,这可能会产生严重影响。对非常大的表建立索引可能需要很多小时,即使对于较小的表,索引构建也会在生产系统无法接受的长时期内锁定写入者。

PostgreSQL 支持在不锁定写入的情况下构建索引。通过指定同时选项创建索引.当使用这个选项时,PostgreSQL 必须对表执行两次扫描,此外它必须等待所有可能修改或使用索引的现有事务终止。因此,与标准索引构建相比,此方法需要更多的总工作量,并且需要更长的时间才能完成。但是,由于它允许在构建索引时继续正常操作,因此此方法对于在生产环境中添加新索引很有用。当然,索引创建带来的额外 CPU 和 I/O 负载可能会减慢其他操作。

在并发索引构建中,索引实际上是在一个事务中输入到系统目录中,然后在另外两个事务中发生两次表扫描。在每次表扫描之前,索引构建必须等待已修改表的现有事务终止。在第二次扫描之后,索引构建必须等待任何具有快照的事务(请参阅第 13 章) 在第二次扫描终止之前终止,包括在其他表上构建的并发索引的任何阶段使用的事务,如果所涉及的索引是部分索引或具有不是简单列引用的列。然后最后可以将索引标记为可以使用,并且创建索引命令终止。然而,即便如此,索引也可能无法立即用于查询:在最坏的情况下,只要在索引构建开始之前存在事务,它就无法使用。

如果在扫描表时出现问题,例如死锁或唯一索引中的唯一性违规,则创建索引命令将失败但留下一个“无效”的索引。出于查询目的,该索引将被忽略,因为它可能不完整;但是它仍然会消耗更新开销。psql\d命令将报告这样的索引无效的

postgres=# \d tab
       Table "public.tab"
 Column |  Type   | Collation | Nullable | Default
## Notes

 See [Chapter 11](indexes.html) for information about when indexes can be used, when they are not used, and in which particular situations they can be useful.

 Currently, only the B-tree, GiST, GIN, and BRIN index methods support multiple-key-column indexes. Whether there can be multiple key columns is independent of whether `INCLUDE` columns can be added to the index. Indexes can have up to 32 columns, including `INCLUDE` columns. (This limit can be altered when building PostgreSQL.) Only B-tree currently supports unique indexes.

 An *operator class* with optional parameters can be specified for each column of an index. The operator class identifies the operators to be used by the index for that column. For example, a B-tree index on four-byte integers would use the `int4_ops` class; this operator class includes comparison functions for four-byte integers. In practice the default operator class for the column's data type is usually sufficient. The main point of having operator classes is that for some data types, there could be more than one meaningful ordering. For example, we might want to sort a complex-number data type either by absolute value or by real part. We could do this by defining two operator classes for the data type and then selecting the proper class when creating an index. More information about operator classes is in [Section 11.10](indexes-opclass.html) and in [Section 38.16](xindex.html).

 When `CREATE INDEX` is invoked on a partitioned table, the default behavior is to recurse to all partitions to ensure they all have matching indexes. Each partition is first checked to determine whether an equivalent index already exists, and if so, that index will become attached as a partition index to the index being created, which will become its parent index. If no matching index exists, a new index will be created and automatically attached; the name of the new index in each partition will be determined as if no index name had been specified in the command. If the `ONLY` option is specified, no recursion is done, and the index is marked invalid. (`ALTER INDEX ... ATTACH PARTITION` marks the index valid, once all partitions acquire matching indexes.) Note, however, that any partition that is created in the future using `CREATE TABLE ... PARTITION OF` will automatically have a matching index, regardless of whether `ONLY` is specified.

 For index methods that support ordered scans (currently, only B-tree), the optional clauses `ASC`, `DESC`, `NULLS FIRST`, and/or `NULLS LAST` can be specified to modify the sort ordering of the index. Since an ordered index can be scanned either forward or backward, it is not normally useful to create a single-column `DESC` index — that sort ordering is already available with a regular index. The value of these options is that multicolumn indexes can be created that match the sort ordering requested by a mixed-ordering query, such as `SELECT ... ORDER BY x ASC, y DESC`. The `NULLS` options are useful if you need to support “nulls sort low” behavior, rather than the default “nulls sort high”, in queries that depend on indexes to avoid sorting steps.

 The system regularly collects statistics on all of a table's columns. Newly-created non-expression indexes can immediately use these statistics to determine an index's usefulness. For new expression indexes, it is necessary to run [`ANALYZE`](sql-analyze.html) or wait for the [autovacuum daemon](routine-vacuuming.html#AUTOVACUUM) to analyze the table to generate statistics for these indexes.

 For most index methods, the speed of creating an index is dependent on the setting of [maintenance\_work\_mem](runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM). Larger values will reduce the time needed for index creation, so long as you don't make it larger than the amount of memory really available, which would drive the machine into swapping.

PostgreSQL can build indexes while leveraging multiple CPUs in order to process the table rows faster. This feature is known as *parallel index build*. For index methods that support building indexes in parallel (currently, only B-tree), `maintenance_work_mem` specifies the maximum amount of memory that can be used by each index build operation as a whole, regardless of how many worker processes were started. Generally, a cost model automatically determines how many worker processes should be requested, if any.

 Parallel index builds may benefit from increasing `maintenance_work_mem` where an equivalent serial index build will see little or no benefit. Note that `maintenance_work_mem` may influence the number of worker processes requested, since parallel workers must have at least a `32MB` share of the total `maintenance_work_mem` budget. There must also be a remaining `32MB` share for the leader process. Increasing [max\_parallel\_maintenance\_workers](runtime-config-resource.html#GUC-MAX-PARALLEL-MAINTENANCE-WORKERS) may allow more workers to be used, which will reduce the time needed for index creation, so long as the index build is not already I/O bound. Of course, there should also be sufficient CPU capacity that would otherwise lie idle.

 Setting a value for `parallel_workers` via [`ALTER TABLE`](sql-altertable.html) directly controls how many parallel worker processes will be requested by a `CREATE INDEX` against the table. This bypasses the cost model completely, and prevents `maintenance_work_mem` from affecting how many parallel workers are requested. Setting `parallel_workers` to 0 via `ALTER TABLE` will disable parallel index builds on the table in all cases.

### Tip

 You might want to reset `parallel_workers` after setting it as part of tuning an index build. This avoids inadvertent changes to query plans, since `parallel_workers` affects *all* parallel table scans.

 While `CREATE INDEX` with the `CONCURRENTLY` option supports parallel builds without special restrictions, only the first table scan is actually performed in parallel.

 Use [`DROP INDEX`](sql-dropindex.html) to remove an index.

 Like any long-running transaction, `CREATE INDEX` on a table can affect which tuples can be removed by concurrent `VACUUM` on any other table. Excepted from this are operations with the `CONCURRENTLY` option for indexes that are not partial and do not index any expressions.

 Prior releases of PostgreSQL also had an R-tree index method. This method has been removed because it had no significant advantages over the GiST method. If `USING rtree` is specified, `CREATE INDEX` will interpret it as `USING gist`, to simplify conversion of old databases to GiST.

 Each backend running `CREATE INDEX` will report its progress in the `pg_stat_progress_create_index` view. See [Section 28.4.2](progress-reporting.html#CREATE-INDEX-PROGRESS-REPORTING) for details.

## Examples

 To create a unique B-tree index on the column `title` in the table `films`:

创建唯一索引 title_idx ON 电影(标题);

 To create a unique B-tree index on the column `title` with included columns `director` and `rating` in the table `films`:

CREATE UNIQUE INDEX title_idx ON电影(标题)包括(导演,评级);

 To create a B-Tree index with deduplication disabled:

CREATE INDEX title_idx ON 电影 (title) WITH (deduplicate_items = off);

 To create an index on the expression `lower(title)`, allowing efficient case-insensitive searches:

为电影创建索引 ((lower(title)));

 (In this example we have chosen to omit the index name, so the system will choose a name, typically `films_lower_idx`.)

 To create an index with non-default collation:

CREATE INDEX title_idx_german ON 电影(标题 COLLATE “de_DE”);

 To create an index with non-default sort ordering of nulls:

创建索引 title_idx_nulls_low ON 电影(标题 NULLS FIRST);

 To create an index with non-default fill factor:

在电影(标题)上创建唯一索引 title_idx(填充因子 = 70);

 To create a GIN index with fast updates disabled:

CREATE INDEX gin_idx ON documents_table USING GIN (locations) WITH (fastupdate = off);

 To create an index on the column `code` in the table `films` and have the index reside in the tablespace `indexspace`:

CREATE INDEX code_idx ON 电影(代码)TABLESPACE 索引空间;

 To create a GiST index on a point attribute so that we can efficiently use box operators on the result of the conversion function:

CREATE INDEX pointloc ON points USING gist (box(location,location));SELECT * FROM points WHERE box(location,location) && '(0,0),(1,1)'::box;

 To create an index without locking out writes to the table:

在sales_table(数量)上同时创建索引sales_quantity_index;

## Compatibility

`CREATE INDEX` is a PostgreSQL language extension. There are no provisions for indexes in the SQL standard.

## See Also

[ALTER INDEX](sql-alterindex.html), [DROP INDEX](sql-dropindex.html), [REINDEX](sql-reindex.html), [Section 28.4.2](progress-reporting.html#CREATE-INDEX-PROGRESS-REPORTING)