{"Entry":{"collection":"sql","key":"create-index","name":"CREATE INDEX","aliases":["createindex"],"metadata":{"aliases":["createindex"],"changed_in":["6.5","7.0","7.2","7.4","8.0","8.2","8.3","9.0","9.1","9.2","9.5","11","13","15"],"changes":[{"from":"6.4","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":[],"removed":[]},"status":"changed","synopsis":{"added":["( func_name( r\"\u003ecolle\u003e [, ... ]) ops_name )"],"removed":["( func_name( column [, ... ]) ops_name )"]},"to":"6.5"},{"from":"6.5","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["description"],"removed":[]},"status":"changed","synopsis":{"added":["[ USING acc_name ] ( func_name( column [, ... ]) [ ops_name ] )"],"removed":["( func_name( r\"\u003ecolle\u003e [, ... ]) ops_name )"]},"to":"7.0"},{"from":"7.0","purpose_changed":false,"renamed":{"from_file":"sql-createindex.htm","to_file":"sql-createindex.html"},"sections":{"added":[],"changed":["description"],"removed":[]},"status":"changed","synopsis":null,"to":"7.1"},{"from":"7.1","purpose_changed":true,"renamed":null,"sections":{"added":[],"changed":["description","usage","compatibility"],"removed":[]},"status":"changed","synopsis":{"added":["[ USING acc_method ] ( column [ ops_name ] [, ...] )","[ WHERE predicate ]","[ USING acc_method ] ( func_name( column [, ... ]) [ ops_name ] )","[ WHERE predicate ]"],"removed":["[ USING acc_name ] ( column [ ops_name ] [, ...] )","[ USING acc_name ] ( func_name( column [, ... ]) [ ops_name ] )"]},"to":"7.2"},{"from":"7.2","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["description"],"removed":[]},"status":"changed","synopsis":null,"to":"7.3"},{"from":"7.3","purpose_changed":false,"renamed":null,"sections":{"added":["parameters","notes","examples"],"changed":["description","compatibility"],"removed":["usage"]},"status":"changed","synopsis":{"added":["CREATE [ UNIQUE ] INDEX name ON table [ USING method ]","( { column | ( expression ) } [ opclass ] [, ...] )"],"removed":["CREATE [ UNIQUE ] INDEX index_name ON table","[ USING acc_method ] ( column [ ops_name ] [, ...] )","CREATE [ UNIQUE ] INDEX index_name ON table","[ USING acc_method ] ( func_name( column [, ... ]) [ ops_name ] )","[ WHERE predicate ]"]},"to":"7.4"},{"from":"7.4","purpose_changed":false,"renamed":null,"sections":{"added":["see_also"],"changed":["description","parameters","notes","examples"],"removed":[]},"status":"changed","synopsis":{"added":["[ TABLESPACE tablespace ]","[ WHERE predicate ]"],"removed":[]},"to":"8.0"},{"from":"8.0","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["notes"],"removed":[]},"status":"changed","synopsis":null,"to":"8.1"},{"from":"8.1","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["description","parameters","notes","examples"],"removed":[]},"status":"changed","synopsis":{"added":["CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] name ON table [ USING method ]","[ WITH ( storage_parameter = value [, ... ] ) ]","[ TABLESPACE tablespace ]"],"removed":[]},"to":"8.2"},{"from":"8.2","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["description","parameters","notes","examples"],"removed":[]},"status":"changed","synopsis":{"added":["( { column | ( expression ) } [ opclass ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] )"],"removed":[]},"to":"8.3"},{"from":"8.3","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["description","parameters","notes","examples"],"removed":[]},"status":"changed","synopsis":null,"to":"8.4"},{"from":"8.4","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["description","parameters","notes","examples"],"removed":[]},"status":"changed","synopsis":{"added":["CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ name ] ON table [ USING method ]"],"removed":[]},"to":"9.0"},{"from":"9.0","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["parameters","notes","examples"],"removed":[]},"status":"changed","synopsis":{"added":["( { column | ( expression ) } [ COLLATE collation ] [ opclass ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] )"],"removed":[]},"to":"9.1"},{"from":"9.1","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["description","parameters"],"removed":[]},"status":"changed","synopsis":{"added":["CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ name ] ON table_name [ USING method ]","( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] )","[ TABLESPACE tablespace_name ]"],"removed":["CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ name ] ON table [ USING method ]","( { column | ( expression ) } [ COLLATE collation ] [ opclass ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] )","[ TABLESPACE tablespace ]"]},"to":"9.2"},{"from":"9.2","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["description","parameters"],"removed":[]},"status":"changed","synopsis":null,"to":"9.3"},{"from":"9.3","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["parameters"],"removed":[]},"status":"changed","synopsis":null,"to":"9.4"},{"from":"9.4","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["description","parameters","notes","examples"],"removed":[]},"status":"changed","synopsis":{"added":["CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] name ] ON table_name [ USING method ]","[ WITH ( storage_parameter [= value] [, ... ] ) ]"],"removed":[]},"to":"9.5"},{"from":"9.5","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["parameters","notes"],"removed":[]},"status":"changed","synopsis":null,"to":"9.6"},{"from":"9.6","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["description","parameters","notes"],"removed":[]},"status":"changed","synopsis":null,"to":"10"},{"from":"10","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["parameters","notes","examples"],"removed":[]},"status":"changed","synopsis":{"added":["CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] name ] ON [ ONLY ] table_name [ USING method ]","[ INCLUDE ( column_name [, ...] ) ]","[ WITH ( storage_parameter [= value] [, ... ] ) ]"],"removed":[]},"to":"11"},{"from":"11","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["parameters","notes","see_also"],"removed":[]},"status":"changed","synopsis":null,"to":"12"},{"from":"12","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["parameters","notes","examples"],"removed":[]},"status":"changed","synopsis":{"added":["( { column_name | ( expression ) } [ COLLATE collation ] [ opclass [ ( opclass_parameter = value [, ... ] ) ] ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] )"],"removed":[]},"to":"13"},{"from":"13","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["parameters","notes","see_also"],"removed":[]},"status":"changed","synopsis":null,"to":"14"},{"from":"14","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["parameters"],"removed":[]},"status":"changed","synopsis":{"added":["[ NULLS [ NOT ] DISTINCT ]","[ WITH ( storage_parameter [= value] [, ... ] ) ]"],"removed":[]},"to":"15"},{"from":"15","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["notes","see_also"],"removed":[]},"status":"changed","synopsis":null,"to":"16"},{"from":"16","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["parameters","notes","see_also"],"removed":[]},"status":"changed","synopsis":null,"to":"17"},{"from":"17","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["parameters","notes"],"removed":[]},"status":"changed","synopsis":null,"to":"18"}],"content_hash":"04f7ad4b127ff5bff99fe0e83d3a02c50dbf8ad4902355981a5f4a428b8bcb64","editorial":{},"first_version":"6.4","group":"index","imported_at":"2026-09-30T17:43:36.854471+08:00","last_version":"20","name":"CREATE INDEX","object":"INDEX","position":1001,"present_in":["6.4","6.5","7.0","7.1","7.2","7.3","7.4","8.0","8.1","8.2","8.3","8.4","9.0","9.1","9.2","9.3","9.4","9.5","9.6","10","11","12","13","14","15","16","17","18","19","20"],"purpose":"define a new index","purpose_zh":"","related":["alter-index","drop-index","reindex"],"slug":"create-index","source_rev":"a709ab85","synopsis":"CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] name ] ON [ ONLY ] table_name [ USING method ]\n( { column_name | ( expression ) } [ COLLATE collation ] [ opclass [ ( opclass_parameter = value [, ... ] ) ] ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] )\n[ INCLUDE ( column_name [, ...] ) ]\n[ NULLS [ NOT ] DISTINCT ]\n[ WITH ( storage_parameter [= value] [, ... ] ) ]\n[ TABLESPACE tablespace_name ]\n[ WHERE predicate ]","verb":"CREATE"}},"Definition":{"Collection":"sql","Key":"create-index","SourceDatabase":"center","Version":"18","SourceTable":"sqlcmd","SourceKey":"create-index","SourceRevision":"a709ab85","Facts":{"anchor":"SQL-CREATEINDEX","file":"sql-createindex.html","lang":"en","name":"CREATE INDEX","purpose":"define a new index","purpose_zh":"","related":["alter-index","drop-index","reindex"],"sections":[{"html":"\u003cp\u003e\u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e constructs an index on the specified column(s) of the specified relation, which can be a table or a materialized view. Indexes are primarily used to enhance database performance (though inappropriate use can result in slower performance).\u003c/p\u003e\u003cp\u003eThe key field(s) for the index are specified as column names, or alternatively as expressions written in parentheses. Multiple fields can be specified if the index method supports multicolumn indexes.\u003c/p\u003e\u003cp\u003eAn index field can be an expression computed from the values of one or more columns of the table row. This feature can be used to obtain fast access to data based on some transformation of the basic data. For example, an index computed on \u003ccode class=\"literal\"\u003eupper(col)\u003c/code\u003e would allow the clause \u003ccode class=\"literal\"\u003eWHERE upper(col) = 'JIM'\u003c/code\u003e to use an index.\u003c/p\u003e\u003cp\u003e\u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e provides the index methods B-tree, hash, GiST, SP-GiST, GIN, and BRIN. Users can also define their own index methods, but that is fairly complicated.\u003c/p\u003e\u003cp\u003eWhen the \u003ccode class=\"literal\"\u003eWHERE\u003c/code\u003e clause is present, a \u003cem class=\"firstterm\"\u003epartial index\u003c/em\u003e is created. A partial index is an index that contains entries for only a portion of a table, usually a portion that is more useful for indexing than the rest of the table. For example, if you have a table that contains both billed and unbilled orders where the unbilled orders take up a small fraction of the total table and yet that is an often used section, you can improve performance by creating an index on just that portion. Another possible application is to use \u003ccode class=\"literal\"\u003eWHERE\u003c/code\u003e with \u003ccode class=\"literal\"\u003eUNIQUE\u003c/code\u003e to enforce uniqueness over a subset of a table. See \u003ca href=\"/docs/18/indexes-partial.html\" title=\"11.8. Partial Indexes\"\u003eSection 11.8\u003c/a\u003e for more discussion.\u003c/p\u003e\u003cp\u003eThe expression used in the \u003ccode class=\"literal\"\u003eWHERE\u003c/code\u003e clause can refer only to columns of the underlying table, but it can use all columns, not just the ones being indexed. Presently, subqueries and aggregate expressions are also forbidden in \u003ccode class=\"literal\"\u003eWHERE\u003c/code\u003e. The same restrictions apply to index fields that are expressions.\u003c/p\u003e\u003cp\u003eAll functions and operators used in an index definition must be \u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003eimmutable\u003c/span\u003e”\u003c/span\u003e, that is, their results must depend only on their arguments and never on any outside influence (such as the contents of another table or the current time). This restriction ensures that the behavior of the index is well-defined. To use a user-defined function in an index expression or \u003ccode class=\"literal\"\u003eWHERE\u003c/code\u003e clause, remember to mark the function immutable when you create it.\u003c/p\u003e","key":"description","title":"Description"},{"html":"\u003cdiv class=\"variablelist\"\u003e\u003cdl class=\"variablelist\"\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eUNIQUE\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eCauses the system to check for duplicate values in the table when the index is created (if data already exist) and each time data is added. Attempts to insert or update data which would result in duplicate entries will generate an error.\u003c/p\u003e\u003cp\u003eAdditional restrictions apply when unique indexes are applied to partitioned tables; see \u003ca href=\"/docs/18/sql-createtable.html\" title=\"CREATE TABLE\"\u003e\u003cspan class=\"refentrytitle\"\u003eCREATE TABLE\u003c/span\u003e\u003c/a\u003e.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eCONCURRENTLY\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eWhen this option is used, \u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e will build the index without taking any locks that prevent concurrent inserts, updates, or deletes on the table; whereas a standard index build locks out writes (but not reads) on the table until it's done. There are several caveats to be aware of when using this option — see \u003ca href=\"/docs/18/sql-createindex.html#SQL-CREATEINDEX-CONCURRENTLY\" title=\"Building Indexes Concurrently\"\u003eBuilding Indexes Concurrently\u003c/a\u003e below.\u003c/p\u003e\u003cp\u003eFor temporary tables, \u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e is always non-concurrent, as no other session can access them, and non-concurrent index creation is cheaper.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eIF NOT EXISTS\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eDo not throw an error if a relation with the same name already exists. A notice is issued in this case. Note that there is no guarantee that the existing index is anything like the one that would have been created. Index name is required when \u003ccode class=\"literal\"\u003eIF NOT EXISTS\u003c/code\u003e is specified.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eINCLUDE\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eThe optional \u003ccode class=\"literal\"\u003eINCLUDE\u003c/code\u003e clause specifies a list of columns which will be included in the index as \u003cem class=\"firstterm\"\u003enon-key\u003c/em\u003e columns. A non-key column cannot be used in an index scan search qualification, and it is disregarded for purposes of any uniqueness or exclusion constraint enforced by the index. However, an index-only scan can return the contents of non-key columns without having to visit the index's table, since they are available directly from the index entry. Thus, addition of non-key columns allows index-only scans to be used for queries that otherwise could not use them.\u003c/p\u003e\u003cp\u003eIt's wise to be conservative about adding non-key columns to an index, especially wide columns. If an index tuple exceeds the maximum size allowed for the index type, data insertion will fail. In any case, non-key columns duplicate data from the index's table and bloat the size of the index, thus potentially slowing searches. Furthermore, B-tree deduplication is never used with indexes that have a non-key column.\u003c/p\u003e\u003cp\u003eColumns listed in the \u003ccode class=\"literal\"\u003eINCLUDE\u003c/code\u003e clause don't need appropriate operator classes; the clause can include columns whose data types don't have operator classes defined for a given access method.\u003c/p\u003e\u003cp\u003eExpressions are not supported as included columns since they cannot be used in index-only scans.\u003c/p\u003e\u003cp\u003eCurrently, the B-tree, GiST and SP-GiST index access methods support this feature. In these indexes, the values of columns listed in the \u003ccode class=\"literal\"\u003eINCLUDE\u003c/code\u003e clause are included in leaf tuples which correspond to heap tuples, but are not included in upper-level index entries used for tree navigation.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eThe name of the index to be created. No schema name can be included here; the index is always created in the same schema as its parent table. The name of the index must be distinct from the name of any other relation (table, sequence, index, view, materialized view, or foreign table) in that schema. If the name is omitted, \u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e chooses a suitable name based on the parent table's name and the indexed column name(s).\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eONLY\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eIndicates not to recurse creating indexes on partitions, if the table is partitioned. The default is to recurse.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003etable_name\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eThe name (possibly schema-qualified) of the table to be indexed.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003emethod\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eThe name of the index method to be used. Choices are \u003ccode class=\"literal\"\u003ebtree\u003c/code\u003e, \u003ccode class=\"literal\"\u003ehash\u003c/code\u003e, \u003ccode class=\"literal\"\u003egist\u003c/code\u003e, \u003ccode class=\"literal\"\u003espgist\u003c/code\u003e, \u003ccode class=\"literal\"\u003egin\u003c/code\u003e, \u003ccode class=\"literal\"\u003ebrin\u003c/code\u003e, or user-installed access methods like \u003ca href=\"/docs/18/bloom.html\" title=\"F.6. bloom — bloom filter index access method\"\u003ebloom\u003c/a\u003e. The default method is \u003ccode class=\"literal\"\u003ebtree\u003c/code\u003e.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003ecolumn_name\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eThe name of a column of the table.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003eexpression\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eAn expression based on one or more columns of the table. The expression usually must be written with surrounding parentheses, as shown in the syntax. However, the parentheses can be omitted if the expression has the form of a function call.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003ecollation\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eThe name of the collation to use for the index. By default, the index uses the collation declared for the column to be indexed or the result collation of the expression to be indexed. Indexes with non-default collations can be useful for queries that involve expressions using non-default collations.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003eopclass\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eThe name of an operator class. See below for details.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003eopclass_parameter\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eThe name of an operator class parameter. See below for details.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eASC\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eSpecifies ascending sort order (which is the default).\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eDESC\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eSpecifies descending sort order.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eNULLS FIRST\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eSpecifies that nulls sort before non-nulls. This is the default when \u003ccode class=\"literal\"\u003eDESC\u003c/code\u003e is specified.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eNULLS LAST\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eSpecifies that nulls sort after non-nulls. This is the default when \u003ccode class=\"literal\"\u003eDESC\u003c/code\u003e is not specified.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eNULLS DISTINCT\u003c/code\u003e\u003cbr\u003e\u003c/span\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eNULLS NOT DISTINCT\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eSpecifies whether for a unique index, null values should be considered distinct (not equal). The default is that they are distinct, so that a unique index could contain multiple null values in a column.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003estorage_parameter\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eThe name of an index-method-specific storage parameter. See \u003ca href=\"/docs/18/sql-createindex.html#SQL-CREATEINDEX-STORAGE-PARAMETERS\" title=\"Index Storage Parameters\"\u003eIndex Storage Parameters\u003c/a\u003e below for details.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003etablespace_name\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eThe tablespace in which to create the index. If not specified, \u003ca href=\"/docs/18/runtime-config-client.html#GUC-DEFAULT-TABLESPACE\"\u003edefault_tablespace\u003c/a\u003e is consulted, or \u003ca href=\"/docs/18/runtime-config-client.html#GUC-TEMP-TABLESPACES\"\u003etemp_tablespaces\u003c/a\u003e for indexes on temporary tables.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003epredicate\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eThe constraint expression for a partial index.\u003c/p\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003cdiv class=\"refsect2\"\u003e\u003ch3\u003eIndex Storage Parameters\u003c/h3\u003e\u003cp\u003eThe optional \u003ccode class=\"literal\"\u003eWITH\u003c/code\u003e clause specifies \u003cem class=\"firstterm\"\u003estorage parameters\u003c/em\u003e for the index. Each index method has its own set of allowed storage parameters.\u003c/p\u003e\u003cp\u003eThe B-tree, hash, GiST and SP-GiST index methods all accept this parameter:\u003c/p\u003e\u003cdiv class=\"variablelist\"\u003e\u003cdl class=\"variablelist\"\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003efillfactor\u003c/code\u003e (\u003ccode class=\"type\"\u003einteger\u003c/code\u003e) \u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eControls how full the index method will try to pack index pages. For B-trees, leaf pages are filled to this percentage during initial index builds, and also when extending the index at the right (adding new largest key values). If pages subsequently become completely full, they will be split, leading to fragmentation of the on-disk index structure. B-trees use a default fillfactor of 90, but any integer value from 10 to 100 can be selected.\u003c/p\u003e\u003cp\u003eB-tree indexes on tables where many inserts and/or updates are anticipated can benefit from lower fillfactor settings at \u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e time (following bulk loading into the table). Values in the range of 50 - 90 can usefully \u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003esmooth out\u003c/span\u003e”\u003c/span\u003e the \u003cspan class=\"emphasis\"\u003e\u003cem\u003erate\u003c/em\u003e\u003c/span\u003e of page splits during the early life of the B-tree index (lowering fillfactor like this may even lower the absolute number of page splits, though this effect is highly workload dependent). The B-tree bottom-up index deletion technique described in \u003ca href=\"/docs/18/btree.html#BTREE-DELETION\" title=\"65.1.4.2. Bottom-up Index Deletion\"\u003eSection 65.1.4.2\u003c/a\u003e is dependent on having some \u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003eextra\u003c/span\u003e”\u003c/span\u003e space on pages to store \u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003eextra\u003c/span\u003e”\u003c/span\u003e tuple versions, and so can be affected by fillfactor (though the effect is usually not significant).\u003c/p\u003e\u003cp\u003eIn other specific cases it might be useful to increase fillfactor to 100 at \u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e time as a way of maximizing space utilization. You should only consider this when you are completely sure that the table is static (i.e. that it will never be affected by either inserts or updates). A fillfactor setting of 100 otherwise risks \u003cspan class=\"emphasis\"\u003e\u003cem\u003eharming\u003c/em\u003e\u003c/span\u003e performance: even a few updates or inserts will cause a sudden flood of page splits.\u003c/p\u003e\u003cp\u003eThe other index methods use fillfactor in different but roughly analogous ways; the default fillfactor varies between methods.\u003c/p\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003cp\u003eB-tree indexes additionally accept this parameter:\u003c/p\u003e\u003cdiv class=\"variablelist\"\u003e\u003cdl class=\"variablelist\"\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003ededuplicate_items\u003c/code\u003e (\u003ccode class=\"type\"\u003eboolean\u003c/code\u003e) \u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eControls usage of the B-tree deduplication technique described in \u003ca href=\"/docs/18/btree.html#BTREE-DEDUPLICATION\" title=\"65.1.4.3. Deduplication\"\u003eSection 65.1.4.3\u003c/a\u003e. Set to \u003ccode class=\"literal\"\u003eON\u003c/code\u003e or \u003ccode class=\"literal\"\u003eOFF\u003c/code\u003e to enable or disable the optimization. (Alternative spellings of \u003ccode class=\"literal\"\u003eON\u003c/code\u003e and \u003ccode class=\"literal\"\u003eOFF\u003c/code\u003e are allowed as described in \u003ca href=\"/docs/18/config-setting.html\" title=\"19.1. Setting Parameters\"\u003eSection 19.1\u003c/a\u003e.) The default is \u003ccode class=\"literal\"\u003eON\u003c/code\u003e.\u003c/p\u003e\u003cdiv class=\"note\"\u003e\u003ch3\u003eNote\u003c/h3\u003e\u003cp\u003eTurning \u003ccode class=\"literal\"\u003ededuplicate_items\u003c/code\u003e off via \u003ccode class=\"command\"\u003eALTER INDEX\u003c/code\u003e prevents future insertions from triggering deduplication, but does not in itself make existing posting list tuples use the standard tuple representation.\u003c/p\u003e\u003c/div\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003cp\u003eGiST indexes additionally accept this parameter:\u003c/p\u003e\u003cdiv class=\"variablelist\"\u003e\u003cdl class=\"variablelist\"\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003ebuffering\u003c/code\u003e (\u003ccode class=\"type\"\u003eenum\u003c/code\u003e) \u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eControls whether the buffered build technique described in \u003ca href=\"/docs/18/gist.html#GIST-BUFFERING-BUILD\" title=\"65.2.4.1. GiST Index Build Methods\"\u003eSection 65.2.4.1\u003c/a\u003e is used to build the index. With \u003ccode class=\"literal\"\u003eOFF\u003c/code\u003e buffering is disabled, with \u003ccode class=\"literal\"\u003eON\u003c/code\u003e it is enabled, and with \u003ccode class=\"literal\"\u003eAUTO\u003c/code\u003e it is initially disabled, but is turned on on-the-fly once the index size reaches \u003ca href=\"/docs/18/runtime-config-query.html#GUC-EFFECTIVE-CACHE-SIZE\"\u003eeffective_cache_size\u003c/a\u003e. The default is \u003ccode class=\"literal\"\u003eAUTO\u003c/code\u003e. Note that if sorted build is possible, it will be used instead of buffered build unless \u003ccode class=\"literal\"\u003ebuffering=ON\u003c/code\u003e is specified.\u003c/p\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003cp\u003eGIN indexes accept these parameters:\u003c/p\u003e\u003cdiv class=\"variablelist\"\u003e\u003cdl class=\"variablelist\"\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003efastupdate\u003c/code\u003e (\u003ccode class=\"type\"\u003eboolean\u003c/code\u003e) \u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eControls usage of the fast update technique described in \u003ca href=\"/docs/18/gin.html#GIN-FAST-UPDATE\" title=\"65.4.4.1. GIN Fast Update Technique\"\u003eSection 65.4.4.1\u003c/a\u003e. \u003ccode class=\"literal\"\u003eON\u003c/code\u003e enables fast update, \u003ccode class=\"literal\"\u003eOFF\u003c/code\u003e disables it. The default is \u003ccode class=\"literal\"\u003eON\u003c/code\u003e.\u003c/p\u003e\u003cdiv class=\"note\"\u003e\u003ch3\u003eNote\u003c/h3\u003e\u003cp\u003eTurning \u003ccode class=\"literal\"\u003efastupdate\u003c/code\u003e off via \u003ccode class=\"command\"\u003eALTER INDEX\u003c/code\u003e prevents future insertions from going into the list of pending index entries, but does not in itself flush existing entries. You might want to \u003ccode class=\"command\"\u003eVACUUM\u003c/code\u003e the table or call the \u003ccode class=\"function\"\u003egin_clean_pending_list\u003c/code\u003e function afterward to ensure the pending list is emptied.\u003c/p\u003e\u003c/div\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003cdiv class=\"variablelist\"\u003e\u003cdl class=\"variablelist\"\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003egin_pending_list_limit\u003c/code\u003e (\u003ccode class=\"type\"\u003einteger\u003c/code\u003e) \u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eOverrides the global setting of \u003ca href=\"/docs/18/runtime-config-client.html#GUC-GIN-PENDING-LIST-LIMIT\"\u003egin_pending_list_limit\u003c/a\u003e for this index. This value is specified in kilobytes.\u003c/p\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003cp\u003e\u003cacronym\u003eBRIN\u003c/acronym\u003e indexes accept these parameters:\u003c/p\u003e\u003cdiv class=\"variablelist\"\u003e\u003cdl class=\"variablelist\"\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003epages_per_range\u003c/code\u003e (\u003ccode class=\"type\"\u003einteger\u003c/code\u003e) \u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eDefines the number of table blocks that make up one block range for each entry of a \u003cacronym\u003eBRIN\u003c/acronym\u003e index (see \u003ca href=\"/docs/18/brin.html#BRIN-INTRO\" title=\"65.5.1. Introduction\"\u003eSection 65.5.1\u003c/a\u003e for more details). The default is \u003ccode class=\"literal\"\u003e128\u003c/code\u003e.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eautosummarize\u003c/code\u003e (\u003ccode class=\"type\"\u003eboolean\u003c/code\u003e) \u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eDefines whether a summarization run is queued for the previous page range whenever an insertion is detected on the next one (see \u003ca href=\"/docs/18/brin.html#BRIN-OPERATION\" title=\"65.5.1.1. Index Maintenance\"\u003eSection 65.5.1.1\u003c/a\u003e for more details). The default is \u003ccode class=\"literal\"\u003eoff\u003c/code\u003e.\u003c/p\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv class=\"refsect2\"\u003e\u003ch3\u003eBuilding Indexes Concurrently\u003c/h3\u003e\u003cp\u003eCreating an index can interfere with regular operation of a database. Normally \u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e locks the table to be indexed against writes and performs the entire index build with a single scan of the table. Other transactions can still read the table, but if they try to insert, update, or delete rows in the table they will block until the index build is finished. This could have a severe effect if the system is a live production database. Very large tables can take many hours to be indexed, and even for smaller tables, an index build can lock out writers for periods that are unacceptably long for a production system.\u003c/p\u003e\u003cp\u003e\u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e supports building indexes without locking out writes. This method is invoked by specifying the \u003ccode class=\"literal\"\u003eCONCURRENTLY\u003c/code\u003e option of \u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e. When this option is used, \u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e must perform two scans of the table, and in addition it must wait for all existing transactions that could potentially modify or use the index to terminate. Thus this method requires more total work than a standard index build and takes significantly longer to complete. However, since it allows normal operations to continue while the index is built, this method is useful for adding new indexes in a production environment. Of course, the extra CPU and I/O load imposed by the index creation might slow other operations.\u003c/p\u003e\u003cp\u003eIn a concurrent index build, the index is actually entered as an \u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003einvalid\u003c/span\u003e”\u003c/span\u003e index into the system catalogs in one transaction, then two table scans occur in two more transactions. Before each table scan, the index build must wait for existing transactions that have modified the table to terminate. After the second scan, the index build must wait for any transactions that have a snapshot (see \u003ca href=\"/docs/18/mvcc.html\" title=\"Chapter 13. Concurrency Control\"\u003eChapter 13\u003c/a\u003e) predating the second scan to terminate, including transactions used by any phase of concurrent index builds on other tables, if the indexes involved are partial or have columns that are not simple column references. Then finally the index can be marked \u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003evalid\u003c/span\u003e”\u003c/span\u003e and ready for use, and the \u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e command terminates. Even then, however, the index may not be immediately usable for queries: in the worst case, it cannot be used as long as transactions exist that predate the start of the index build.\u003c/p\u003e\u003cp\u003eIf a problem arises while scanning the table, such as a deadlock or a uniqueness violation in a unique index, the \u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e command will fail but leave behind an \u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003einvalid\u003c/span\u003e”\u003c/span\u003e index. This index will be ignored for querying purposes because it might be incomplete; however it will still consume update overhead. The \u003cspan class=\"application\"\u003epsql\u003c/span\u003e \u003ccode class=\"command\"\u003e\\d\u003c/code\u003e command will report such an index as \u003ccode class=\"literal\"\u003eINVALID\u003c/code\u003e:\u003c/p\u003e\u003cpre class=\"programlisting\"\u003epostgres=# \\d tab\n       Table \"public.tab\"\n Column |  Type   | Collation | Nullable | Default\n--------+---------+-----------+----------+---------\n col    | integer |           |          |\nIndexes:\n    \"idx\" btree (col) INVALID\n\u003c/pre\u003e\u003cp\u003eThe recommended recovery method in such cases is to drop the index and try again to perform \u003ccode class=\"command\"\u003eCREATE INDEX CONCURRENTLY\u003c/code\u003e. (Another possibility is to rebuild the index with \u003ccode class=\"command\"\u003eREINDEX INDEX CONCURRENTLY\u003c/code\u003e).\u003c/p\u003e\u003cp\u003eAnother caveat when building a unique index concurrently is that the uniqueness constraint is already being enforced against other transactions when the second table scan begins. This means that constraint violations could be reported in other queries prior to the index becoming available for use, or even in cases where the index build eventually fails. Also, if a failure does occur in the second scan, the \u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003einvalid\u003c/span\u003e”\u003c/span\u003e index continues to enforce its uniqueness constraint afterwards.\u003c/p\u003e\u003cp\u003eConcurrent builds of expression indexes and partial indexes are supported. Errors occurring in the evaluation of these expressions could cause behavior similar to that described above for unique constraint violations.\u003c/p\u003e\u003cp\u003eRegular index builds permit other regular index builds on the same table to occur simultaneously, but only one concurrent index build can occur on a table at a time. In either case, schema modification of the table is not allowed while the index is being built. Another difference is that a regular \u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e command can be performed within a transaction block, but \u003ccode class=\"command\"\u003eCREATE INDEX CONCURRENTLY\u003c/code\u003e cannot.\u003c/p\u003e\u003cp\u003eConcurrent builds for indexes on partitioned tables are currently not supported. However, you may concurrently build the index on each partition individually and then finally create the partitioned index non-concurrently in order to reduce the time where writes to the partitioned table will be locked out. In this case, building the partitioned index is a metadata only operation.\u003c/p\u003e\u003c/div\u003e","key":"parameters","title":"Parameters"},{"html":"\u003cp\u003eSee \u003ca href=\"/docs/18/indexes.html\" title=\"Chapter 11. Indexes\"\u003eChapter 11\u003c/a\u003e for information about when indexes can be used, when they are not used, and in which particular situations they can be useful.\u003c/p\u003e\u003cp\u003eCurrently, 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 \u003ccode class=\"literal\"\u003eINCLUDE\u003c/code\u003e columns can be added to the index. Indexes can have up to 32 columns, including \u003ccode class=\"literal\"\u003eINCLUDE\u003c/code\u003e columns. (This limit can be altered when building \u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e.) Only B-tree currently supports unique indexes.\u003c/p\u003e\u003cp\u003eAn \u003cem class=\"firstterm\"\u003eoperator class\u003c/em\u003e 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 \u003ccode class=\"literal\"\u003eint4_ops\u003c/code\u003e 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 \u003ca href=\"/docs/18/indexes-opclass.html\" title=\"11.10. Operator Classes and Operator Families\"\u003eSection 11.10\u003c/a\u003e and in \u003ca href=\"/docs/18/xindex.html\" title=\"36.16. Interfacing Extensions to Indexes\"\u003eSection 36.16\u003c/a\u003e.\u003c/p\u003e\u003cp\u003eWhen \u003ccode class=\"literal\"\u003eCREATE INDEX\u003c/code\u003e 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 \u003ccode class=\"literal\"\u003eONLY\u003c/code\u003e option is specified, no recursion is done, and the index is marked invalid. (\u003ccode class=\"command\"\u003eALTER INDEX ... ATTACH PARTITION\u003c/code\u003e marks the index valid, once all partitions acquire matching indexes.) Note, however, that any partition that is created in the future using \u003ccode class=\"command\"\u003eCREATE TABLE ... PARTITION OF\u003c/code\u003e will automatically have a matching index, regardless of whether \u003ccode class=\"literal\"\u003eONLY\u003c/code\u003e is specified.\u003c/p\u003e\u003cp\u003eFor index methods that support ordered scans (currently, only B-tree), the optional clauses \u003ccode class=\"literal\"\u003eASC\u003c/code\u003e, \u003ccode class=\"literal\"\u003eDESC\u003c/code\u003e, \u003ccode class=\"literal\"\u003eNULLS FIRST\u003c/code\u003e, and/or \u003ccode class=\"literal\"\u003eNULLS LAST\u003c/code\u003e 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 \u003ccode class=\"literal\"\u003eDESC\u003c/code\u003e 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 \u003ccode class=\"literal\"\u003eSELECT ... ORDER BY x ASC, y DESC\u003c/code\u003e. The \u003ccode class=\"literal\"\u003eNULLS\u003c/code\u003e options are useful if you need to support \u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003enulls sort low\u003c/span\u003e”\u003c/span\u003e behavior, rather than the default \u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003enulls sort high\u003c/span\u003e”\u003c/span\u003e, in queries that depend on indexes to avoid sorting steps.\u003c/p\u003e\u003cp\u003eThe 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 \u003ca href=\"/docs/18/sql-analyze.html\" title=\"ANALYZE\"\u003e\u003ccode class=\"command\"\u003eANALYZE\u003c/code\u003e\u003c/a\u003e or wait for the \u003ca href=\"/docs/18/routine-vacuuming.html#AUTOVACUUM\" title=\"24.1.6. The Autovacuum Daemon\"\u003eautovacuum daemon\u003c/a\u003e to analyze the table to generate statistics for these indexes.\u003c/p\u003e\u003cp\u003eWhile \u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e is running, the \u003ca href=\"/docs/18/runtime-config-client.html#GUC-SEARCH-PATH\"\u003esearch_path\u003c/a\u003e is temporarily changed to \u003ccode class=\"literal\"\u003epg_catalog, pg_temp\u003c/code\u003e.\u003c/p\u003e\u003cp\u003eFor most index methods, the speed of creating an index is dependent on the setting of \u003ca href=\"/docs/18/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM\"\u003emaintenance_work_mem\u003c/a\u003e. 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.\u003c/p\u003e\u003cp\u003e\u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e can build indexes while leveraging multiple CPUs in order to process the table rows faster. This feature is known as \u003cem class=\"firstterm\"\u003eparallel index build\u003c/em\u003e. For index methods that support building indexes in parallel (currently, B-tree, GIN, and BRIN), \u003ccode class=\"varname\"\u003emaintenance_work_mem\u003c/code\u003e 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.\u003c/p\u003e\u003cp\u003eParallel index builds may benefit from increasing \u003ccode class=\"varname\"\u003emaintenance_work_mem\u003c/code\u003e where an equivalent serial index build will see little or no benefit. Note that \u003ccode class=\"varname\"\u003emaintenance_work_mem\u003c/code\u003e may influence the number of worker processes requested, since parallel workers must have at least a \u003ccode class=\"literal\"\u003e32MB\u003c/code\u003e share of the total \u003ccode class=\"varname\"\u003emaintenance_work_mem\u003c/code\u003e budget. There must also be a remaining \u003ccode class=\"literal\"\u003e32MB\u003c/code\u003e share for the leader process. Increasing \u003ca href=\"/docs/18/runtime-config-resource.html#GUC-MAX-PARALLEL-MAINTENANCE-WORKERS\"\u003emax_parallel_maintenance_workers\u003c/a\u003e 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.\u003c/p\u003e\u003cp\u003eSetting a value for \u003ccode class=\"literal\"\u003eparallel_workers\u003c/code\u003e via \u003ca href=\"/docs/18/sql-altertable.html\" title=\"ALTER TABLE\"\u003e\u003ccode class=\"command\"\u003eALTER TABLE\u003c/code\u003e\u003c/a\u003e directly controls how many parallel worker processes will be requested by a \u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e against the table. This bypasses the cost model completely, and prevents \u003ccode class=\"varname\"\u003emaintenance_work_mem\u003c/code\u003e from affecting how many parallel workers are requested. Setting \u003ccode class=\"literal\"\u003eparallel_workers\u003c/code\u003e to 0 via \u003ccode class=\"command\"\u003eALTER TABLE\u003c/code\u003e will disable parallel index builds on the table in all cases.\u003c/p\u003e\u003cdiv class=\"tip\"\u003e\u003ch3\u003eTip\u003c/h3\u003e\u003cp\u003eYou might want to reset \u003ccode class=\"literal\"\u003eparallel_workers\u003c/code\u003e after setting it as part of tuning an index build. This avoids inadvertent changes to query plans, since \u003ccode class=\"literal\"\u003eparallel_workers\u003c/code\u003e affects \u003cspan class=\"emphasis\"\u003e\u003cem\u003eall\u003c/em\u003e\u003c/span\u003e parallel table scans.\u003c/p\u003e\u003c/div\u003e\u003cp\u003eWhile \u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e with the \u003ccode class=\"literal\"\u003eCONCURRENTLY\u003c/code\u003e option supports parallel builds without special restrictions, only the first table scan is actually performed in parallel.\u003c/p\u003e\u003cp\u003eUse \u003ca href=\"/docs/18/sql-dropindex.html\" title=\"DROP INDEX\"\u003e\u003ccode class=\"command\"\u003eDROP INDEX\u003c/code\u003e\u003c/a\u003e to remove an index.\u003c/p\u003e\u003cp\u003eLike any long-running transaction, \u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e on a table can affect which tuples can be removed by concurrent \u003ccode class=\"command\"\u003eVACUUM\u003c/code\u003e on any other table.\u003c/p\u003e\u003cp\u003ePrior releases of \u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e also had an R-tree index method. This method has been removed because it had no significant advantages over the GiST method. If \u003ccode class=\"literal\"\u003eUSING rtree\u003c/code\u003e is specified, \u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e will interpret it as \u003ccode class=\"literal\"\u003eUSING gist\u003c/code\u003e, to simplify conversion of old databases to GiST.\u003c/p\u003e\u003cp\u003eEach backend running \u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e will report its progress in the \u003ccode class=\"structname\"\u003epg_stat_progress_create_index\u003c/code\u003e view. See \u003ca href=\"/docs/18/progress-reporting.html#CREATE-INDEX-PROGRESS-REPORTING\" title=\"27.4.4. CREATE INDEX Progress Reporting\"\u003eSection 27.4.4\u003c/a\u003e for details.\u003c/p\u003e","key":"notes","title":"Notes"},{"html":"\u003cp\u003eTo create a unique B-tree index on the column \u003ccode class=\"literal\"\u003etitle\u003c/code\u003e in the table \u003ccode class=\"literal\"\u003efilms\u003c/code\u003e:\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eCREATE UNIQUE INDEX title_idx ON films (title);\n\u003c/pre\u003e\u003cp\u003eTo create a unique B-tree index on the column \u003ccode class=\"literal\"\u003etitle\u003c/code\u003e with included columns \u003ccode class=\"literal\"\u003edirector\u003c/code\u003e and \u003ccode class=\"literal\"\u003erating\u003c/code\u003e in the table \u003ccode class=\"literal\"\u003efilms\u003c/code\u003e:\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eCREATE UNIQUE INDEX title_idx ON films (title) INCLUDE (director, rating);\n\u003c/pre\u003e\u003cp\u003eTo create a B-Tree index with deduplication disabled:\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eCREATE INDEX title_idx ON films (title) WITH (deduplicate_items = off);\n\u003c/pre\u003e\u003cp\u003eTo create an index on the expression \u003ccode class=\"literal\"\u003elower(title)\u003c/code\u003e, allowing efficient case-insensitive searches:\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eCREATE INDEX ON films ((lower(title)));\n\u003c/pre\u003e\u003cp\u003e(In this example we have chosen to omit the index name, so the system will choose a name, typically \u003ccode class=\"literal\"\u003efilms_lower_idx\u003c/code\u003e.)\u003c/p\u003e\u003cp\u003eTo create an index with non-default collation:\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eCREATE INDEX title_idx_german ON films (title COLLATE \"de_DE\");\n\u003c/pre\u003e\u003cp\u003eTo create an index with non-default sort ordering of nulls:\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eCREATE INDEX title_idx_nulls_low ON films (title NULLS FIRST);\n\u003c/pre\u003e\u003cp\u003eTo create an index with non-default fill factor:\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eCREATE UNIQUE INDEX title_idx ON films (title) WITH (fillfactor = 70);\n\u003c/pre\u003e\u003cp\u003eTo create a \u003cacronym\u003eGIN\u003c/acronym\u003e index with fast updates disabled:\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eCREATE INDEX gin_idx ON documents_table USING GIN (locations) WITH (fastupdate = off);\n\u003c/pre\u003e\u003cp\u003eTo create an index on the column \u003ccode class=\"literal\"\u003ecode\u003c/code\u003e in the table \u003ccode class=\"literal\"\u003efilms\u003c/code\u003e and have the index reside in the tablespace \u003ccode class=\"literal\"\u003eindexspace\u003c/code\u003e:\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eCREATE INDEX code_idx ON films (code) TABLESPACE indexspace;\n\u003c/pre\u003e\u003cp\u003eTo create a GiST index on a point attribute so that we can efficiently use box operators on the result of the conversion function:\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eCREATE INDEX pointloc\n    ON points USING gist (box(location,location));\nSELECT * FROM points\n    WHERE box(location,location) \u0026amp;\u0026amp; '(0,0),(1,1)'::box;\n\u003c/pre\u003e\u003cp\u003eTo create an index without locking out writes to the table:\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eCREATE INDEX CONCURRENTLY sales_quantity_index ON sales_table (quantity);\n\u003c/pre\u003e","key":"examples","title":"Examples"},{"html":"\u003cp\u003e\u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e is a \u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e language extension. There are no provisions for indexes in the SQL standard.\u003c/p\u003e","key":"compatibility","title":"Compatibility"},{"html":"\u003cspan class=\"simplelist\"\u003e\u003ca href=\"/wiki/sql/alter-index/?v=18\" title=\"ALTER INDEX\"\u003e\u003cspan class=\"refentrytitle\"\u003eALTER INDEX\u003c/span\u003e\u003c/a\u003e, \u003ca href=\"/wiki/sql/drop-index/?v=18\" title=\"DROP INDEX\"\u003e\u003cspan class=\"refentrytitle\"\u003eDROP INDEX\u003c/span\u003e\u003c/a\u003e, \u003ca href=\"/wiki/sql/reindex/?v=18\" title=\"REINDEX\"\u003e\u003cspan class=\"refentrytitle\"\u003eREINDEX\u003c/span\u003e\u003c/a\u003e, \u003ca href=\"/docs/18/progress-reporting.html#CREATE-INDEX-PROGRESS-REPORTING\" title=\"27.4.4. CREATE INDEX Progress Reporting\"\u003eSection 27.4.4\u003c/a\u003e\u003c/span\u003e","key":"see_also","title":"See Also"}],"sections_same_as":"","slug":"18","synopsis_html":"CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] \u003cem class=\"replaceable\"\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/em\u003e ] ON [ ONLY ] \u003cem class=\"replaceable\"\u003e\u003ccode\u003etable_name\u003c/code\u003e\u003c/em\u003e [ USING \u003cem class=\"replaceable\"\u003e\u003ccode\u003emethod\u003c/code\u003e\u003c/em\u003e ]\n    ( { \u003cem class=\"replaceable\"\u003e\u003ccode\u003ecolumn_name\u003c/code\u003e\u003c/em\u003e | ( \u003cem class=\"replaceable\"\u003e\u003ccode\u003eexpression\u003c/code\u003e\u003c/em\u003e ) } [ COLLATE \u003cem class=\"replaceable\"\u003e\u003ccode\u003ecollation\u003c/code\u003e\u003c/em\u003e ] [ \u003cem class=\"replaceable\"\u003e\u003ccode\u003eopclass\u003c/code\u003e\u003c/em\u003e [ ( \u003cem class=\"replaceable\"\u003e\u003ccode\u003eopclass_parameter\u003c/code\u003e\u003c/em\u003e = \u003cem class=\"replaceable\"\u003e\u003ccode\u003evalue\u003c/code\u003e\u003c/em\u003e [, ... ] ) ] ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] )\n    [ INCLUDE ( \u003cem class=\"replaceable\"\u003e\u003ccode\u003ecolumn_name\u003c/code\u003e\u003c/em\u003e [, ...] ) ]\n    [ NULLS [ NOT ] DISTINCT ]\n    [ WITH ( \u003cem class=\"replaceable\"\u003e\u003ccode\u003estorage_parameter\u003c/code\u003e\u003c/em\u003e [= \u003cem class=\"replaceable\"\u003e\u003ccode\u003evalue\u003c/code\u003e\u003c/em\u003e] [, ... ] ) ]\n    [ TABLESPACE \u003cem class=\"replaceable\"\u003e\u003ccode\u003etablespace_name\u003c/code\u003e\u003c/em\u003e ]\n    [ WHERE \u003cem class=\"replaceable\"\u003e\u003ccode\u003epredicate\u003c/code\u003e\u003c/em\u003e ]","synopsis_text":"CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] name ] ON [ ONLY ] table_name [ USING method ]\n( { column_name | ( expression ) } [ COLLATE collation ] [ opclass [ ( opclass_parameter = value [, ... ] ) ] ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] )\n[ INCLUDE ( column_name [, ...] ) ]\n[ NULLS [ NOT ] DISTINCT ]\n[ WITH ( storage_parameter [= value] [, ... ] ) ]\n[ TABLESPACE tablespace_name ]\n[ WHERE predicate ]"},"ManualEvidence":{},"MeasuredEvidence":{}},"Text":{"Collection":"sql","Key":"create-index","SourceDatabase":"pgweb","Version":"18","Locale":"zh-Hans","Title":"CREATE INDEX","Summary":"定义一个新索引","BodyHTML":"\u003cpre\u003eCREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] name ] ON [ ONLY ] table_name [ USING method ]\n( { column_name | ( expression ) } [ COLLATE collation ] [ opclass [ ( opclass_parameter = value [, ... ] ) ] ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] )\n[ INCLUDE ( column_name [, ...] ) ]\n[ NULLS [ NOT ] DISTINCT ]\n[ WITH ( storage_parameter [= value] [, ... ] ) ]\n[ TABLESPACE tablespace_name ]\n[ WHERE predicate ]\u003c/pre\u003e\u003csection\u003e\u003ch2\u003e描述\u003c/h2\u003e\u003cp\u003e\u003ccode\u003eCREATE INDEX\u003c/code\u003e在指定关系的指定列上构建一个索引，该关系可以是表或物化视图。索引主要用于提升数据库性能（但使用不当也可能导致性能下降）。\u003c/p\u003e\u003cp\u003e索引的键字段指定为列名，或者指定为写在圆括号中的表达式。如果索引方法支持多列索引，则可以指定多个字段。\u003c/p\u003e\u003cp\u003e索引字段可以是根据表行中一个或多个列值计算得到的表达式。该特性可用于根据基础数据的某种变换来快速访问数据。例如，在\u003ccode\u003eupper(col)\u003c/code\u003e上计算的索引可让子句 \u003ccode\u003eWHERE upper(col) = \u0026#39;JIM\u0026#39;\u003c/code\u003e使用索引。\u003c/p\u003e\u003cp\u003e\u003cspan\u003ePostgreSQL\u003c/span\u003e提供了索引方法 B-树、hash、GiST、SP-GiST、GIN 以及 BRIN。用户也可以定义自己的索引方法，但这相当复杂。\u003c/p\u003e\u003cp\u003e当\u003ccode\u003eWHERE\u003c/code\u003e子句存在时，会创建一个\u003cem\u003e部分索引\u003c/em\u003e。部分索引只包含表中一部分行的索引项，通常这一部分比表的其余部分更适合建立索引。例如，如果一个表同时包含已开票和未开票订单，而未开票订单只占整个表的一小部分，但这一部分又经常被访问，就可以只对这部分创建索引来提升性能。另一种可能的应用是将\u003ccode\u003eWHERE\u003c/code\u003e与\u003ccode\u003eUNIQUE\u003c/code\u003e结合使用，以便在表的一个子集上强制唯一性。更多讨论请见\u003ca href=\"/docs/18/indexes-partial.html\" rel=\"nofollow\"\u003e第 11.8 节\u003c/a\u003e。\u003c/p\u003e\u003cp\u003e\u003ccode\u003eWHERE\u003c/code\u003e子句中使用的表达式只能引用底层表的列，但它可以使用所有列，而不仅仅是被索引的列。当前，\u003ccode\u003eWHERE\u003c/code\u003e中也禁止使用子查询和聚合表达式。同样的限制也适用于作为表达式的索引字段。\u003c/p\u003e\u003cp\u003e所有在索引定义中使用的函数和操作符都必须是\u003cspan\u003e“\u003cspan\u003e不可变的\u003c/span\u003e”\u003c/span\u003e，也就是说，它们的结果只能依赖其参数，而不能受任何外部因素影响（例如另一个表的内容或当前时间）。这种限制确保索引的行为定义明确。要在索引表达式或\u003ccode\u003eWHERE\u003c/code\u003e子句中使用用户定义的函数，记得在创建该函数时将其标记为不可变。\u003c/p\u003e\u003c/section\u003e\u003csection\u003e\u003ch2\u003e参数\u003c/h2\u003e\u003cdiv\u003e\u003cdl\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003eUNIQUE\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e使系统在创建索引时（如果数据已经存在）以及每次添加数据时，检查表中的重复值。任何会导致重复项的插入或更新操作都会报错。\u003c/p\u003e\u003cp\u003e当唯一索引用于分区表时，还会有额外限制；参见\u003ca href=\"/docs/18/sql-createtable.html\" title=\"CREATE TABLE\" rel=\"nofollow\"\u003e\u003cspan\u003eCREATE TABLE\u003c/span\u003e\u003c/a\u003e。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003eCONCURRENTLY\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e当使用了这个选项时，\u003cspan\u003ePostgreSQL\u003c/span\u003e在构建索引时不会取得任何会阻止该表上并发插入、更新或删除的锁。而标准的索引构建会阻止该表上的写入（但不会阻止读取），直到索引构建完成。使用这个选项时有若干注意事项 — 请见\u003ca href=\"/docs/18/sql-createindex.html#SQL-CREATEINDEX-CONCURRENTLY\" title=\"并发构建索引\" rel=\"nofollow\"\u003eBuilding Indexes Concurrently\u003c/a\u003e。\u003c/p\u003e\u003cp\u003e对于临时表，\u003ccode\u003eCREATE INDEX\u003c/code\u003e始终是非并发的，因为没有其他会话可以访问它们，而且非并发创建索引的代价更低。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003eIF NOT EXISTS\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e如果同名关系已存在，则不抛出错误，而是发出一个提示。注意，现有索引并不保证与本应创建的索引有任何相似之处。指定 \u003ccode\u003eIF NOT EXISTS\u003c/code\u003e时，必须提供索引名。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003eINCLUDE\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e可选的\u003ccode\u003eINCLUDE\u003c/code\u003e子句指定一个列列表，这些列将作为\u003cem\u003e非键\u003c/em\u003e列包含在索引中。非键列不能用作索引扫描的搜索限定条件，在索引强制执行的任何唯一性或排他约束中也会被忽略。不过，非键列的内容可以由仅索引扫描返回，而无需访问索引对应的表，因为它们可直接从索引项中取得。因此，添加非键列可以让原本无法使用仅索引扫描的查询也能使用它。\u003c/p\u003e\u003cp\u003e对于向索引中添加非键列，采取保守态度是明智的，尤其是宽列。如果索引元组超过该索引类型允许的最大尺寸，数据插入将失败。无论如何，非键列都会复制索引对应表中的数据并增大索引体积，因此可能拖慢搜索。此外，B-树去重技术绝不会用于带有非键列的索引。\u003c/p\u003e\u003cp\u003e\u003ccode\u003eINCLUDE\u003c/code\u003e子句中列出的列不需要合适的操作符类；该子句可以包含数据类型尚未为给定访问方法定义操作符类的列。\u003c/p\u003e\u003cp\u003e不支持将表达式作为内含列，因为它们不能用于仅索引扫描。\u003c/p\u003e\u003cp\u003e当前，B-树、GiST 和 SP-GiST 索引访问方法支持此特性。在这些索引中，\u003ccode\u003eINCLUDE\u003c/code\u003e子句所列出的列的值会包含在与堆元组对应的叶子元组中，但不会包含在用于树导航的上层索引项中。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003cem\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e要创建的索引的名称。这里不能包含模式名称；索引总是在其父表所在的模式中创建。索引的名称必须与该模式中的任何其他关系（表、序列、索引、视图、物化视图或外部表）的名称不同。如果省略名称，\u003cspan\u003ePostgreSQL\u003c/span\u003e会根据父表的名称和索引列的名称选择一个合适的名称。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003eONLY\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e表示如果该表是分区表，则不要递归地在各分区上创建索引。默认会递归。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003cem\u003e\u003ccode\u003etable_name\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e要建立索引的表名（可以是模式限定名）。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003cem\u003e\u003ccode\u003emethod\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e要使用的索引方法的名称。选择包括\u003ccode\u003ebtree\u003c/code\u003e、\u003ccode\u003ehash\u003c/code\u003e、\u003ccode\u003egist\u003c/code\u003e、\u003ccode\u003espgist\u003c/code\u003e、\u003ccode\u003egin\u003c/code\u003e、\u003ccode\u003ebrin\u003c/code\u003e，或用户安装的访问方法，如 \u003ca href=\"/docs/18/bloom.html\" rel=\"nofollow\"\u003ebloom\u003c/a\u003e。默认方法是\u003ccode\u003ebtree\u003c/code\u003e。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003cem\u003e\u003ccode\u003ecolumn_name\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e一个表列的名称。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003cem\u003e\u003ccode\u003eexpression\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e一个基于表中一个或多个列的表达式。通常必须像语法中所示那样写在外围圆括号中。不过，如果该表达式是函数调用形式，则可以省略圆括号。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003cem\u003e\u003ccode\u003ecollation\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e将用于该索引的排序规则名称。默认情况下，索引使用被索引列声明的排序规则，或者被索引表达式的结果排序规则。对于涉及使用非默认排序规则表达式的查询，使用非默认排序规则的索引可能会很有用。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003cem\u003e\u003ccode\u003eopclass\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e一个操作符类的名称。详见下文。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003cem\u003e\u003ccode\u003eopclass_parameter\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e一个操作符类参数的名称。详见下文。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003eASC\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e指定升序排序（默认）。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003eDESC\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e指定降序排序。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003eNULLS FIRST\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e指定把空值排序在非空值前面。在指定\u003ccode\u003eDESC\u003c/code\u003e时，这是默认行为。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003eNULLS LAST\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e指定把空值排序在非空值后面。在没有指定\u003ccode\u003eDESC\u003c/code\u003e时，这是默认行为。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003eNULLS DISTINCT\u003c/code\u003e\u003cbr\u003e\u003c/span\u003e\u003cspan\u003e\u003ccode\u003eNULLS NOT DISTINCT\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e指定对于唯一索引，是否应将空值视为不同（而非相等）。默认情况下，它们是不同的，因此唯一索引可以在列中包含多个空值。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003cem\u003e\u003ccode\u003estorage_parameter\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e索引方法相关的存储参数的名称。详见\u003ca href=\"/docs/18/sql-createindex.html#SQL-CREATEINDEX-STORAGE-PARAMETERS\" title=\"索引存储参数\" rel=\"nofollow\"\u003eIndex Storage Parameters\u003c/a\u003e。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003cem\u003e\u003ccode\u003etablespace_name\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e在其中创建索引的表空间。如果未指定，将查阅\u003ca href=\"/docs/18/runtime-config-client.html#GUC-DEFAULT-TABLESPACE\" rel=\"nofollow\"\u003edefault_tablespace\u003c/a\u003e；对于临时表上的索引，则查阅\u003ca href=\"/docs/18/runtime-config-client.html#GUC-TEMP-TABLESPACES\" rel=\"nofollow\"\u003etemp_tablespaces\u003c/a\u003e。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003cem\u003e\u003ccode\u003epredicate\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e部分索引的约束表达式。\u003c/p\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003cdiv\u003e\u003ch3\u003e索引存储参数\u003c/h3\u003e\u003cp\u003e可选的\u003ccode\u003eWITH\u003c/code\u003e子句为索引指定\u003cem\u003e存储参数\u003c/em\u003e。每一种索引方法都有其各自允许的存储参数集合。\u003c/p\u003e\u003cp\u003eB-树、hash、GiST 和 SP-GiST 索引方法都接受以下参数：\u003c/p\u003e\u003cdiv\u003e\u003cdl\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003efillfactor\u003c/code\u003e (\u003ccode\u003einteger\u003c/code\u003e) \u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e控制索引方法尝试将索引页填充到多满。对于 B-树，在初始构建索引时，以及在右侧扩展索引（加入新的最大键值）时，叶子页都会填充到这一百分比。如果页面随后变成全满，就会发生分裂，从而导致磁盘上的索引结构碎片化。B-树默认使用 90 的填充因子，但也可以选择 10 到 100 之间的任意整数值。\u003c/p\u003e\u003cp\u003e对预计会有大量插入和/或更新的表，在\u003ccode\u003eCREATE INDEX\u003c/code\u003e 时为 B-树索引设置较低的填充因子会有好处（即在向表批量装载数据之后）。50 到 90 范围内的值可以有效地\u003cspan\u003e“\u003cspan\u003e平滑\u003c/span\u003e”\u003c/span\u003eB-树索引生命周期早期页面分裂的\u003cspan\u003e\u003cem\u003e速率\u003c/em\u003e\u003c/span\u003e（这样降低填充因子甚至可能减少页面分裂的绝对数量，不过这一效果高度依赖工作负载）。\u003ca href=\"/docs/18/btree.html#BTREE-DELETION\" rel=\"nofollow\"\u003e第 65.1.4.2 节\u003c/a\u003e中描述的 B-树自底向上索引删除技术依赖于页面上有一些\u003cspan\u003e“\u003cspan\u003e额外\u003c/span\u003e”\u003c/span\u003e空间来存储\u003cspan\u003e“\u003cspan\u003e额外\u003c/span\u003e”\u003c/span\u003e的元组版本，因此也会受到填充因子影响（不过通常影响不大）。\u003c/p\u003e\u003cp\u003e在某些其他特定情况下，在\u003ccode\u003eCREATE INDEX\u003c/code\u003e时将填充因子提高到 100 可能有助于最大化空间利用率。只有在完全确定该表是静态的（即永远不会受到插入或更新影响）时，才应考虑这样做。否则，将填充因子设为 100 有\u003cspan\u003e\u003cem\u003e损害\u003c/em\u003e\u003c/span\u003e性能的风险：即便只有少量更新或插入，也会导致页面突然大量分裂。\u003c/p\u003e\u003cp\u003e其他索引方法以不同但大致类似的方式使用填充因子；默认填充因子因方法而异。\u003c/p\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003cp\u003eB-树索引还接受以下参数：\u003c/p\u003e\u003cdiv\u003e\u003cdl\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003ededuplicate_items\u003c/code\u003e (\u003ccode\u003eboolean\u003c/code\u003e) \u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e控制是否使用\u003ca href=\"/docs/18/btree.html#BTREE-DEDUPLICATION\" rel=\"nofollow\"\u003e第 65.1.4.3 节\u003c/a\u003e中描述的 B-树去重技术。设置为\u003ccode\u003eON\u003c/code\u003e或\u003ccode\u003eOFF\u003c/code\u003e可启用或禁用该优化。（\u003ccode\u003eON\u003c/code\u003e和\u003ccode\u003eOFF\u003c/code\u003e的其他拼写形式也被接受，如\u003ca href=\"/docs/18/config-setting.html\" rel=\"nofollow\"\u003e第 19.1 节\u003c/a\u003e所述。）默认值为\u003ccode\u003eON\u003c/code\u003e。\u003c/p\u003e\u003cdiv\u003e\u003ch3\u003e注意\u003c/h3\u003e\u003cp\u003e通过\u003ccode\u003eALTER INDEX\u003c/code\u003e关闭\u003ccode\u003ededuplicate_items\u003c/code\u003e 可以防止将来的插入触发去重，但这本身不会让现有倒排列表元组改用标准的元组表示。\u003c/p\u003e\u003c/div\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003cp\u003eGiST 索引还接受以下参数：\u003c/p\u003e\u003cdiv\u003e\u003cdl\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003ebuffering\u003c/code\u003e (\u003ccode\u003eenum\u003c/code\u003e) \u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e控制是否使用\u003ca href=\"/docs/18/gist.html#GIST-BUFFERING-BUILD\" rel=\"nofollow\"\u003e第 65.2.4.1 节\u003c/a\u003e中描述的缓冲构建技术来构建索引。设置为\u003ccode\u003eOFF\u003c/code\u003e时禁用缓冲构建，设置为 \u003ccode\u003eON\u003c/code\u003e时启用，设置为\u003ccode\u003eAUTO\u003c/code\u003e时初始为禁用，但一旦索引大小达到\u003ca href=\"/docs/18/runtime-config-query.html#GUC-EFFECTIVE-CACHE-SIZE\" rel=\"nofollow\"\u003eeffective_cache_size\u003c/a\u003e，就会在运行过程中启用。默认值为\u003ccode\u003eAUTO\u003c/code\u003e。注意，如果可以使用排序构建，则除非指定\u003ccode\u003ebuffering=ON\u003c/code\u003e，否则会改用排序构建而不是缓冲构建。\u003c/p\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003cp\u003eGIN 索引接受以下参数：\u003c/p\u003e\u003cdiv\u003e\u003cdl\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003efastupdate\u003c/code\u003e (\u003ccode\u003eboolean\u003c/code\u003e) \u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e控制\u003ca href=\"/docs/18/gin.html#GIN-FAST-UPDATE\" rel=\"nofollow\"\u003e第 65.4.4.1 节\u003c/a\u003e中描述的快速更新技术的使用。\u003ccode\u003eON\u003c/code\u003e 启用快速更新，\u003ccode\u003eOFF\u003c/code\u003e 禁用快速更新。默认值为\u003ccode\u003eON\u003c/code\u003e。\u003c/p\u003e\u003cdiv\u003e\u003ch3\u003e注意\u003c/h3\u003e\u003cp\u003e通过\u003ccode\u003eALTER INDEX\u003c/code\u003e关闭\u003ccode\u003efastupdate\u003c/code\u003e 会阻止后续插入进入待处理索引项列表，但这本身不会将现有条目移出待处理列表。之后可能需要对该表执行\u003ccode\u003eVACUUM\u003c/code\u003e，或调用 \u003ccode\u003egin_clean_pending_list\u003c/code\u003e函数，以确保待处理列表被清空。\u003c/p\u003e\u003c/div\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdl\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003egin_pending_list_limit\u003c/code\u003e (\u003ccode\u003einteger\u003c/code\u003e) \u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e为该索引覆盖\u003ca href=\"/docs/18/runtime-config-client.html#GUC-GIN-PENDING-LIST-LIMIT\" rel=\"nofollow\"\u003egin_pending_list_limit\u003c/a\u003e的全局设置。该值以千字节为单位。\u003c/p\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003cp\u003e\u003cacronym\u003eBRIN\u003c/acronym\u003e 索引接受以下参数：\u003c/p\u003e\u003cdiv\u003e\u003cdl\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003epages_per_range\u003c/code\u003e (\u003ccode\u003einteger\u003c/code\u003e) \u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e定义每个\u003cacronym\u003eBRIN\u003c/acronym\u003e索引项对应的一个块范围由多少个表块组成（详见\u003ca href=\"/docs/18/brin.html#BRIN-INTRO\" rel=\"nofollow\"\u003e第 65.5.1 节\u003c/a\u003e）。默认值为\u003ccode\u003e128\u003c/code\u003e。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003eautosummarize\u003c/code\u003e (\u003ccode\u003eboolean\u003c/code\u003e) \u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e定义当在下一页范围检测到插入时，是否为前一页范围排队执行一次范围摘要操作（详见\u003ca href=\"/docs/18/brin.html#BRIN-OPERATION\" rel=\"nofollow\"\u003e第 65.5.1.1 节\u003c/a\u003e）。默认值为\u003ccode\u003eoff\u003c/code\u003e。\u003c/p\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003ch3\u003e并发构建索引\u003c/h3\u003e\u003cp\u003e创建索引可能会干扰数据库的正常运行。通常 \u003cspan\u003ePostgreSQL\u003c/span\u003e会锁住要建立索引的表，阻止其写入，并通过一次扫描完成整个索引构建。其他事务仍可读取该表，但如果它们试图在表中插入、更新或删除行，就会阻塞直到索引构建完成。如果系统是在线生产数据库，这可能产生严重影响。对非常大的表建立索引可能需要很多小时，即便是较小的表，索引构建也可能在一段对生产系统而言不可接受的时间内阻止写入者操作。\u003c/p\u003e\u003cp\u003e\u003cspan\u003ePostgreSQL\u003c/span\u003e支持在不阻止写入的情况下构建索引。这种方法通过在\u003ccode\u003eCREATE INDEX\u003c/code\u003e中指定 \u003ccode\u003eCONCURRENTLY\u003c/code\u003e选项来启用。使用该选项时，\u003cspan\u003ePostgreSQL\u003c/span\u003e必须对该表执行两次扫描，此外还必须等待所有现有、可能修改或使用该索引的事务结束。因此，这种方法比标准索引构建需要更多总工作量，完成时间也明显更长。不过，由于它允许在构建索引期间继续进行正常操作，所以这种方法适合在生产环境中新增索引。当然，创建索引带来的额外 CPU 和 I/O 负载也可能拖慢其他操作。\u003c/p\u003e\u003cp\u003e在并发索引构建中，索引实际上会先在一个事务中作为\u003cspan\u003e“\u003cspan\u003e无效\u003c/span\u003e”\u003c/span\u003e索引录入系统目录，然后在另外两个事务中执行两次表扫描。每次表扫描之前，索引构建都必须等待已修改该表的现有事务结束。第二次扫描之后，索引构建还必须等待所有持有早于第二次扫描的快照（参见\u003ca href=\"/docs/18/mvcc.html\" rel=\"nofollow\"\u003e第 13 章\u003c/a\u003e）的事务结束；如果相关索引是部分索引，或包含并非简单列引用的列，这还包括其他表上并发索引构建任何阶段所使用的事务。最后，索引才能被标记为\u003cspan\u003e“\u003cspan\u003e有效\u003c/span\u003e”\u003c/span\u003e并可供使用，而 \u003ccode\u003eCREATE INDEX\u003c/code\u003e命令随之结束。即便如此，索引也未必能立即用于查询：最坏情况下，只要仍存在早于索引构建开始的事务，它就不能被使用。\u003c/p\u003e\u003cp\u003e如果在扫描表时出现问题，例如死锁或唯一索引中的唯一性违反，\u003ccode\u003eCREATE INDEX\u003c/code\u003e命令将失败，但会留下一个\u003cspan\u003e“\u003cspan\u003e无效\u003c/span\u003e”\u003c/span\u003e索引。这个索引在查询时会被忽略，因为它可能不完整；但它仍会带来更新开销。\u003cspan\u003epsql\u003c/span\u003e \u003ccode\u003e\\d\u003c/code\u003e命令会将这样的索引报告为 \u003ccode\u003eINVALID\u003c/code\u003e：\u003c/p\u003e\u003cpre\u003epostgres=# \\d tab\n       Table \u0026#34;public.tab\u0026#34;\n Column |  Type   | Collation | Nullable | Default\n--------+---------+-----------+----------+---------\n col    | integer |           |          |\nIndexes:\n    \u0026#34;idx\u0026#34; btree (col) INVALID\n\u003c/pre\u003e\u003cp\u003e在这种情况下，推荐的恢复方法是删除该索引，然后再次尝试执行 \u003ccode\u003eCREATE INDEX CONCURRENTLY\u003c/code\u003e。（另一种做法是用 \u003ccode\u003eREINDEX INDEX CONCURRENTLY\u003c/code\u003e重建索引。）\u003c/p\u003e\u003cp\u003e并发构建唯一索引时的另一项注意事项是，在第二次表扫描开始时，唯一性约束就已经开始对其他事务生效了。这意味着在该索引可供使用之前，其他查询就可能报告约束违规，甚至在索引构建最终失败的情况下也是如此。另外，如果第二次扫描确实失败了，那个\u003cspan\u003e“\u003cspan\u003e无效\u003c/span\u003e”\u003c/span\u003e索引之后仍会继续强制执行其唯一性约束。\u003c/p\u003e\u003cp\u003e也支持并发构建表达式索引和部分索引。计算这些表达式时发生的错误，可能导致与上文所述唯一性约束违规类似的行为。\u003c/p\u003e\u003cp\u003e普通索引构建允许在同一张表上同时进行其他普通索引构建，但一张表在同一时刻只能发生一次并发索引构建。无论哪种情况，在索引构建期间都不允许修改该表的模式。另一个区别是，普通\u003ccode\u003eCREATE INDEX\u003c/code\u003e 命令可以在事务块内执行，而\u003ccode\u003eCREATE INDEX CONCURRENTLY\u003c/code\u003e 不能。\u003c/p\u003e\u003cp\u003e当前不支持对分区表的索引进行并发构建。不过，可以分别在每个分区上并发构建索引，最后再以非并发方式创建分区索引，从而缩短分区表写入被阻止的时间。在这种情况下，构建分区索引只是元数据操作。\u003c/p\u003e\u003c/div\u003e\u003c/section\u003e\u003csection\u003e\u003ch2\u003e注解\u003c/h2\u003e\u003cp\u003e关于索引何时能被使用、何时不被使用以及什么情况下它们有用的信息请见\u003ca href=\"/docs/18/indexes.html\" rel=\"nofollow\"\u003e第 11 章\u003c/a\u003e。\u003c/p\u003e\u003cp\u003e当前，只有 B-树、GiST、GIN 和 BRIN 索引方法支持多键列索引。能否拥有多个键列，与能否向索引添加\u003ccode\u003eINCLUDE\u003c/code\u003e列无关。索引最多可以有 32 列，包括\u003ccode\u003eINCLUDE\u003c/code\u003e列。（可以在构建\u003cspan\u003ePostgreSQL\u003c/span\u003e时修改这个限制）。当前只有 B-树支持唯一索引。\u003c/p\u003e\u003cp\u003e可以为索引中的每一列指定一个带可选参数的\u003cem\u003e操作符类\u003c/em\u003e。操作符类标识该索引在该列上要使用的操作符。例如，一个四字节整数上的 B-树索引会使用\u003ccode\u003eint4_ops\u003c/code\u003e类；这个操作符类包含用于四字节整数的比较函数。实际上，列数据类型的默认操作符类通常就足够了。引入操作符类的主要原因在于，对于某些数据类型，可能存在不止一种有意义的排序方式。例如，可能需要按绝对值或实部对复数数据类型排序。要做到这一点，可以为该数据类型定义两个操作符类，然后在创建索引时选择合适的类。关于操作符类的更多信息请见\u003ca href=\"/docs/18/indexes-opclass.html\" rel=\"nofollow\"\u003e第 11.10 节\u003c/a\u003e以及\u003ca href=\"/docs/18/xindex.html\" rel=\"nofollow\"\u003e第 36.16 节\u003c/a\u003e。\u003c/p\u003e\u003cp\u003e当在分区表上调用\u003ccode\u003eCREATE INDEX\u003c/code\u003e时，默认行为是递归到所有分区，以确保它们都拥有匹配的索引。系统首先检查每个分区是否已经存在等效索引；如果存在，该索引会作为正在创建索引的分区索引附接到其上，而被创建的索引将成为其父索引。若不存在匹配索引，则会创建一个新索引并自动附着；每个分区中新索引的名称会按命令中未指定索引名时的规则确定。如果指定\u003ccode\u003eONLY\u003c/code\u003e选项，则不进行递归，且该索引会被标记为无效。（一旦所有分区都获得匹配索引，\u003ccode\u003eALTER INDEX ... ATTACH PARTITION\u003c/code\u003e会将该索引标记为有效。）不过请注意，将来使用 \u003ccode\u003eCREATE TABLE ... PARTITION OF\u003c/code\u003e创建的任何分区都会自动拥有匹配索引，无论是否指定了\u003ccode\u003eONLY\u003c/code\u003e。\u003c/p\u003e\u003cp\u003e对于支持有序扫描的索引方法（当前只有 B-树），可以指定可选子句 \u003ccode\u003eASC\u003c/code\u003e、\u003ccode\u003eDESC\u003c/code\u003e、\u003ccode\u003eNULLS FIRST\u003c/code\u003e 和/或\u003ccode\u003eNULLS LAST\u003c/code\u003e来修改索引的排序顺序。由于有序索引可以向前或向后扫描，因此创建单列\u003ccode\u003eDESC\u003c/code\u003e索引通常并无用处 — 常规索引已经提供了这种排序顺序。这些选项的价值在于可以创建与混合排序查询所要求顺序相匹配的多列索引，例如 \u003ccode\u003eSELECT ... ORDER BY x ASC, y DESC\u003c/code\u003e。如果需要在依靠索引避免排序步骤的查询中支持\u003cspan\u003e“\u003cspan\u003e空值排在低位\u003c/span\u003e”\u003c/span\u003e，而不是默认的\u003cspan\u003e“\u003cspan\u003e空值排在高位\u003c/span\u003e”\u003c/span\u003e行为，那么\u003ccode\u003eNULLS\u003c/code\u003e选项就很有用。\u003c/p\u003e\u003cp\u003e系统定期收集表中所有列的统计信息。新创建的非表达式索引可以立即使用这些统计信息来确定索引的有用性。对于新的表达式索引，需要运行 \u003ca href=\"/docs/18/sql-analyze.html\" title=\"ANALYZE\" rel=\"nofollow\"\u003e\u003ccode\u003eANALYZE\u003c/code\u003e\u003c/a\u003e 或等待\u003ca href=\"/docs/18/routine-vacuuming.html#AUTOVACUUM\" rel=\"nofollow\"\u003e自动清理守护进程\u003c/a\u003e分析表以生成这些索引的统计信息。\u003c/p\u003e\u003cp\u003e在 \u003ccode\u003eCREATE INDEX\u003c/code\u003e 执行期间，\u003ca href=\"/docs/18/runtime-config-client.html#GUC-SEARCH-PATH\" rel=\"nofollow\"\u003esearch_path\u003c/a\u003e会被临时设置为 \u003ccode\u003epg_catalog, pg_temp\u003c/code\u003e。\u003c/p\u003e\u003cp\u003e对于大多数索引方法，索引的创建速度取决于\u003ca href=\"/docs/18/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM\" rel=\"nofollow\"\u003emaintenance_work_mem\u003c/a\u003e的设置。较大的值将会减少索引创建所需的时间，当然不要把它设置得超过实际可用的内存量（那会迫使机器进行交换）。\u003c/p\u003e\u003cp\u003e\u003cspan\u003ePostgreSQL\u003c/span\u003e可以在构建索引时利用多个 CPU，以便更快处理表中的行。这项特性被称为\u003cem\u003e并行索引构建\u003c/em\u003e。对于支持并行构建索引的索引方法（当前为 B-树、GIN 和 BRIN），\u003ccode\u003emaintenance_work_mem\u003c/code\u003e指定每次索引构建操作整体最多可使用的内存量，而不管启动了多少工作者进程。通常，代价模型会自动决定是否需要请求工作者进程，以及请求多少个。\u003c/p\u003e\u003cp\u003e增加\u003ccode\u003emaintenance_work_mem\u003c/code\u003e可能会让并行索引构建受益，而等效的串行索引构建则几乎看不到收益。注意，\u003ccode\u003emaintenance_work_mem\u003c/code\u003e可能会影响所请求工作者进程的数量，因为每个并行工作者都必须至少从总的 \u003ccode\u003emaintenance_work_mem\u003c/code\u003e预算中分得\u003ccode\u003e32MB\u003c/code\u003e。领导者进程也必须保留\u003ccode\u003e32MB\u003c/code\u003e。增加\u003ca href=\"/docs/18/runtime-config-resource.html#GUC-MAX-PARALLEL-MAINTENANCE-WORKERS\" rel=\"nofollow\"\u003emax_parallel_maintenance_workers\u003c/a\u003e可能允许使用更多工作者，从而减少索引创建所需时间，前提是索引构建尚未受到 I/O 限制。当然，还应当有足够的、原本会闲置的 CPU 容量。\u003c/p\u003e\u003cp\u003e通过\u003ca href=\"/docs/18/sql-altertable.html\" title=\"ALTER TABLE\" rel=\"nofollow\"\u003e\u003ccode\u003eALTER TABLE\u003c/code\u003e\u003c/a\u003e 为\u003ccode\u003eparallel_workers\u003c/code\u003e设置一个值，可以直接控制 \u003ccode\u003eCREATE INDEX\u003c/code\u003e对该表会请求多少并行工作者进程。这会完全绕过代价模型，也使\u003ccode\u003emaintenance_work_mem\u003c/code\u003e不再影响所请求的并行工作者数量。通过\u003ccode\u003eALTER TABLE\u003c/code\u003e将 \u003ccode\u003eparallel_workers\u003c/code\u003e设置为 0，将在所有情况下禁用该表上的并行索引构建。\u003c/p\u003e\u003cdiv\u003e\u003ch3\u003e提示\u003c/h3\u003e\u003cp\u003e在把\u003ccode\u003eparallel_workers\u003c/code\u003e作为索引构建调优的一部分进行设置后，可能需要将其重置。这样可以避免无意间改变查询计划，因为 \u003ccode\u003eparallel_workers\u003c/code\u003e会影响\u003cspan\u003e\u003cem\u003e所有\u003c/em\u003e\u003c/span\u003e并行表扫描。\u003c/p\u003e\u003c/div\u003e\u003cp\u003e虽然带有\u003ccode\u003eCONCURRENTLY\u003c/code\u003e选项的\u003ccode\u003eCREATE INDEX\u003c/code\u003e 在没有特殊限制的情况下支持并行构建，但实际上只有第一次表扫描会以并行方式执行。\u003c/p\u003e\u003cp\u003e使用\u003ca href=\"/docs/18/sql-dropindex.html\" title=\"DROP INDEX\" rel=\"nofollow\"\u003e\u003ccode\u003eDROP INDEX\u003c/code\u003e\u003c/a\u003e 可以移除索引。\u003c/p\u003e\u003cp\u003e和任何长时间运行的事务一样，在某个表上执行\u003ccode\u003eCREATE INDEX\u003c/code\u003e 会影响在其他任何表上并发执行\u003ccode\u003eVACUUM\u003c/code\u003e时哪些元组可以被移除。\u003c/p\u003e\u003cp\u003e早期版本的\u003cspan\u003ePostgreSQL\u003c/span\u003e还提供过一种 R-tree 索引方法。该方法已经被移除，因为它相对于 GiST 方法并无明显优势。如果指定了\u003ccode\u003eUSING rtree\u003c/code\u003e，\u003ccode\u003eCREATE INDEX\u003c/code\u003e 会将其解释为\u003ccode\u003eUSING gist\u003c/code\u003e，以简化旧数据库向 GiST 的转换。\u003c/p\u003e\u003cp\u003e每个运行\u003ccode\u003eCREATE INDEX\u003c/code\u003e的后端将在 \u003ccode\u003epg_stat_progress_create_index\u003c/code\u003e视图中报告其进度。有关详细信息，请参见\u003ca href=\"/docs/18/progress-reporting.html#CREATE-INDEX-PROGRESS-REPORTING\" rel=\"nofollow\"\u003e第 27.4.4 节\u003c/a\u003e。\u003c/p\u003e\u003c/section\u003e\u003csection\u003e\u003ch2\u003e示例\u003c/h2\u003e\u003cp\u003e要在表\u003ccode\u003efilms\u003c/code\u003e的列\u003ccode\u003etitle\u003c/code\u003e上创建一个唯一 B-树索引：\u003c/p\u003e\u003cpre\u003eCREATE UNIQUE INDEX title_idx ON films (title);\n\u003c/pre\u003e\u003cp\u003e要在表\u003ccode\u003efilms\u003c/code\u003e的列\u003ccode\u003etitle\u003c/code\u003e上创建一个唯一 B-树索引，并将\u003ccode\u003edirector\u003c/code\u003e和\u003ccode\u003erating\u003c/code\u003e作为内含列：\u003c/p\u003e\u003cpre\u003eCREATE UNIQUE INDEX title_idx ON films (title) INCLUDE (director, rating);\n\u003c/pre\u003e\u003cp\u003e要创建一个禁用去重的 B-树索引：\u003c/p\u003e\u003cpre\u003eCREATE INDEX title_idx ON films (title) WITH (deduplicate_items = off);\n\u003c/pre\u003e\u003cp\u003e要在表达式\u003ccode\u003elower(title)\u003c/code\u003e上创建一个索引，以便高效执行不区分大小写的搜索：\u003c/p\u003e\u003cpre\u003eCREATE INDEX ON films ((lower(title)));\n\u003c/pre\u003e\u003cp\u003e（在这个示例中，索引名称被省略，因此系统会选择一个名字，通常为\u003ccode\u003efilms_lower_idx\u003c/code\u003e。）\u003c/p\u003e\u003cp\u003e要创建一个具有非默认排序规则的索引：\u003c/p\u003e\u003cpre\u003eCREATE INDEX title_idx_german ON films (title COLLATE \u0026#34;de_DE\u0026#34;);\n\u003c/pre\u003e\u003cp\u003e要创建一个具有非默认空值排序顺序的索引：\u003c/p\u003e\u003cpre\u003eCREATE INDEX title_idx_nulls_low ON films (title NULLS FIRST);\n\u003c/pre\u003e\u003cp\u003e要创建一个具有非默认填充因子的索引：\u003c/p\u003e\u003cpre\u003eCREATE UNIQUE INDEX title_idx ON films (title) WITH (fillfactor = 70);\n\u003c/pre\u003e\u003cp\u003e要创建一个禁用快速更新的\u003cacronym\u003eGIN\u003c/acronym\u003e索引：\u003c/p\u003e\u003cpre\u003eCREATE INDEX gin_idx ON documents_table USING GIN (locations) WITH (fastupdate = off);\n\u003c/pre\u003e\u003cp\u003e要在表\u003ccode\u003efilms\u003c/code\u003e的列\u003ccode\u003ecode\u003c/code\u003e上创建一个索引，并让该索引驻留在表空间\u003ccode\u003eindexspace\u003c/code\u003e中：\u003c/p\u003e\u003cpre\u003eCREATE INDEX code_idx ON films (code) TABLESPACE indexspace;\n\u003c/pre\u003e\u003cp\u003e要在点属性上创建一个 GiST 索引，以便能够在转换函数的结果上高效地使用 box 操作符：\u003c/p\u003e\u003cpre\u003eCREATE INDEX pointloc\n    ON points USING gist (box(location,location));\nSELECT * FROM points\n    WHERE box(location,location) \u0026amp;\u0026amp; \u0026#39;(0,0),(1,1)\u0026#39;::box;\n\u003c/pre\u003e\u003cp\u003e要在不阻止对表执行写操作的情况下创建索引：\u003c/p\u003e\u003cpre\u003eCREATE INDEX CONCURRENTLY sales_quantity_index ON sales_table (quantity);\n\u003c/pre\u003e\u003c/section\u003e\u003csection\u003e\u003ch2\u003e兼容性\u003c/h2\u003e\u003cp\u003e\u003ccode\u003eCREATE INDEX\u003c/code\u003e是 \u003cspan\u003ePostgreSQL\u003c/span\u003e的语言扩展。SQL 标准中没有关于索引的规定。\u003c/p\u003e\u003c/section\u003e\u003csection\u003e\u003ch2\u003e另见\u003c/h2\u003e\u003cspan\u003e\u003ca href=\"/wiki/sql/alter-index/?v=18\" title=\"ALTER INDEX\" rel=\"nofollow\"\u003e\u003cspan\u003eALTER INDEX\u003c/span\u003e\u003c/a\u003e, \u003ca href=\"/wiki/sql/drop-index/?v=18\" title=\"DROP INDEX\" rel=\"nofollow\"\u003e\u003cspan\u003eDROP INDEX\u003c/span\u003e\u003c/a\u003e, \u003ca href=\"/wiki/sql/reindex/?v=18\" title=\"REINDEX\" rel=\"nofollow\"\u003e\u003cspan\u003eREINDEX\u003c/span\u003e\u003c/a\u003e, \u003ca href=\"/docs/18/progress-reporting.html#CREATE-INDEX-PROGRESS-REPORTING\" rel=\"nofollow\"\u003e第 27.4.4 节\u003c/a\u003e\u003c/span\u003e\u003c/section\u003e","SourceRevision":"1b5ca64c","ContentHash":"c298b1fd1ecb363af26461cf8bc2364f05f3584ec2c68b64ed4a4ccf9fcafc90","Payload":{"purpose_zh":"定义一个新索引","sections":[{"html":"\u003cp\u003e\u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e在指定关系的指定列上构建一个索引，该关系可以是表或物化视图。索引主要用于提升数据库性能（但使用不当也可能导致性能下降）。\u003c/p\u003e\u003cp\u003e索引的键字段指定为列名，或者指定为写在圆括号中的表达式。如果索引方法支持多列索引，则可以指定多个字段。\u003c/p\u003e\u003cp\u003e索引字段可以是根据表行中一个或多个列值计算得到的表达式。该特性可用于根据基础数据的某种变换来快速访问数据。例如，在\u003ccode class=\"literal\"\u003eupper(col)\u003c/code\u003e上计算的索引可让子句 \u003ccode class=\"literal\"\u003eWHERE upper(col) = 'JIM'\u003c/code\u003e使用索引。\u003c/p\u003e\u003cp\u003e\u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e提供了索引方法 B-树、hash、GiST、SP-GiST、GIN 以及 BRIN。用户也可以定义自己的索引方法，但这相当复杂。\u003c/p\u003e\u003cp\u003e当\u003ccode class=\"literal\"\u003eWHERE\u003c/code\u003e子句存在时，会创建一个\u003cem class=\"firstterm\"\u003e部分索引\u003c/em\u003e。部分索引只包含表中一部分行的索引项，通常这一部分比表的其余部分更适合建立索引。例如，如果一个表同时包含已开票和未开票订单，而未开票订单只占整个表的一小部分，但这一部分又经常被访问，就可以只对这部分创建索引来提升性能。另一种可能的应用是将\u003ccode class=\"literal\"\u003eWHERE\u003c/code\u003e与\u003ccode class=\"literal\"\u003eUNIQUE\u003c/code\u003e结合使用，以便在表的一个子集上强制唯一性。更多讨论请见\u003ca href=\"/docs/18/indexes-partial.html\" title=\"11.8. 部分索引\"\u003e第 11.8 节\u003c/a\u003e。\u003c/p\u003e\u003cp\u003e\u003ccode class=\"literal\"\u003eWHERE\u003c/code\u003e子句中使用的表达式只能引用底层表的列，但它可以使用所有列，而不仅仅是被索引的列。当前，\u003ccode class=\"literal\"\u003eWHERE\u003c/code\u003e中也禁止使用子查询和聚合表达式。同样的限制也适用于作为表达式的索引字段。\u003c/p\u003e\u003cp\u003e所有在索引定义中使用的函数和操作符都必须是\u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003e不可变的\u003c/span\u003e”\u003c/span\u003e，也就是说，它们的结果只能依赖其参数，而不能受任何外部因素影响（例如另一个表的内容或当前时间）。这种限制确保索引的行为定义明确。要在索引表达式或\u003ccode class=\"literal\"\u003eWHERE\u003c/code\u003e子句中使用用户定义的函数，记得在创建该函数时将其标记为不可变。\u003c/p\u003e","key":"description","title":"描述"},{"html":"\u003cdiv class=\"variablelist\"\u003e\u003cdl class=\"variablelist\"\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eUNIQUE\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e使系统在创建索引时（如果数据已经存在）以及每次添加数据时，检查表中的重复值。任何会导致重复项的插入或更新操作都会报错。\u003c/p\u003e\u003cp\u003e当唯一索引用于分区表时，还会有额外限制；参见\u003ca href=\"/docs/18/sql-createtable.html\" title=\"CREATE TABLE\"\u003e\u003cspan class=\"refentrytitle\"\u003eCREATE TABLE\u003c/span\u003e\u003c/a\u003e。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eCONCURRENTLY\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e当使用了这个选项时，\u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e在构建索引时不会取得任何会阻止该表上并发插入、更新或删除的锁。而标准的索引构建会阻止该表上的写入（但不会阻止读取），直到索引构建完成。使用这个选项时有若干注意事项 — 请见\u003ca href=\"/docs/18/sql-createindex.html#SQL-CREATEINDEX-CONCURRENTLY\" title=\"并发构建索引\"\u003eBuilding Indexes Concurrently\u003c/a\u003e。\u003c/p\u003e\u003cp\u003e对于临时表，\u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e始终是非并发的，因为没有其他会话可以访问它们，而且非并发创建索引的代价更低。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eIF NOT EXISTS\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e如果同名关系已存在，则不抛出错误，而是发出一个提示。注意，现有索引并不保证与本应创建的索引有任何相似之处。指定 \u003ccode class=\"literal\"\u003eIF NOT EXISTS\u003c/code\u003e时，必须提供索引名。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eINCLUDE\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e可选的\u003ccode class=\"literal\"\u003eINCLUDE\u003c/code\u003e子句指定一个列列表，这些列将作为\u003cem class=\"firstterm\"\u003e非键\u003c/em\u003e列包含在索引中。非键列不能用作索引扫描的搜索限定条件，在索引强制执行的任何唯一性或排他约束中也会被忽略。不过，非键列的内容可以由仅索引扫描返回，而无需访问索引对应的表，因为它们可直接从索引项中取得。因此，添加非键列可以让原本无法使用仅索引扫描的查询也能使用它。\u003c/p\u003e\u003cp\u003e对于向索引中添加非键列，采取保守态度是明智的，尤其是宽列。如果索引元组超过该索引类型允许的最大尺寸，数据插入将失败。无论如何，非键列都会复制索引对应表中的数据并增大索引体积，因此可能拖慢搜索。此外，B-树去重技术绝不会用于带有非键列的索引。\u003c/p\u003e\u003cp\u003e\u003ccode class=\"literal\"\u003eINCLUDE\u003c/code\u003e子句中列出的列不需要合适的操作符类；该子句可以包含数据类型尚未为给定访问方法定义操作符类的列。\u003c/p\u003e\u003cp\u003e不支持将表达式作为内含列，因为它们不能用于仅索引扫描。\u003c/p\u003e\u003cp\u003e当前，B-树、GiST 和 SP-GiST 索引访问方法支持此特性。在这些索引中，\u003ccode class=\"literal\"\u003eINCLUDE\u003c/code\u003e子句所列出的列的值会包含在与堆元组对应的叶子元组中，但不会包含在用于树导航的上层索引项中。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e要创建的索引的名称。这里不能包含模式名称；索引总是在其父表所在的模式中创建。索引的名称必须与该模式中的任何其他关系（表、序列、索引、视图、物化视图或外部表）的名称不同。如果省略名称，\u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e会根据父表的名称和索引列的名称选择一个合适的名称。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eONLY\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e表示如果该表是分区表，则不要递归地在各分区上创建索引。默认会递归。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003etable_name\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e要建立索引的表名（可以是模式限定名）。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003emethod\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e要使用的索引方法的名称。选择包括\u003ccode class=\"literal\"\u003ebtree\u003c/code\u003e、\u003ccode class=\"literal\"\u003ehash\u003c/code\u003e、\u003ccode class=\"literal\"\u003egist\u003c/code\u003e、\u003ccode class=\"literal\"\u003espgist\u003c/code\u003e、\u003ccode class=\"literal\"\u003egin\u003c/code\u003e、\u003ccode class=\"literal\"\u003ebrin\u003c/code\u003e，或用户安装的访问方法，如 \u003ca href=\"/docs/18/bloom.html\" title=\"F.6. bloom — 布隆过滤器索引访问方法\"\u003ebloom\u003c/a\u003e。默认方法是\u003ccode class=\"literal\"\u003ebtree\u003c/code\u003e。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003ecolumn_name\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e一个表列的名称。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003eexpression\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e一个基于表中一个或多个列的表达式。通常必须像语法中所示那样写在外围圆括号中。不过，如果该表达式是函数调用形式，则可以省略圆括号。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003ecollation\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e将用于该索引的排序规则名称。默认情况下，索引使用被索引列声明的排序规则，或者被索引表达式的结果排序规则。对于涉及使用非默认排序规则表达式的查询，使用非默认排序规则的索引可能会很有用。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003eopclass\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e一个操作符类的名称。详见下文。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003eopclass_parameter\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e一个操作符类参数的名称。详见下文。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eASC\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e指定升序排序（默认）。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eDESC\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e指定降序排序。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eNULLS FIRST\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e指定把空值排序在非空值前面。在指定\u003ccode class=\"literal\"\u003eDESC\u003c/code\u003e时，这是默认行为。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eNULLS LAST\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e指定把空值排序在非空值后面。在没有指定\u003ccode class=\"literal\"\u003eDESC\u003c/code\u003e时，这是默认行为。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eNULLS DISTINCT\u003c/code\u003e\u003cbr\u003e\u003c/span\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eNULLS NOT DISTINCT\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e指定对于唯一索引，是否应将空值视为不同（而非相等）。默认情况下，它们是不同的，因此唯一索引可以在列中包含多个空值。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003estorage_parameter\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e索引方法相关的存储参数的名称。详见\u003ca href=\"/docs/18/sql-createindex.html#SQL-CREATEINDEX-STORAGE-PARAMETERS\" title=\"索引存储参数\"\u003eIndex Storage Parameters\u003c/a\u003e。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003etablespace_name\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e在其中创建索引的表空间。如果未指定，将查阅\u003ca href=\"/docs/18/runtime-config-client.html#GUC-DEFAULT-TABLESPACE\"\u003edefault_tablespace\u003c/a\u003e；对于临时表上的索引，则查阅\u003ca href=\"/docs/18/runtime-config-client.html#GUC-TEMP-TABLESPACES\"\u003etemp_tablespaces\u003c/a\u003e。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003epredicate\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e部分索引的约束表达式。\u003c/p\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003cdiv class=\"refsect2\"\u003e\u003ch3\u003e索引存储参数\u003c/h3\u003e\u003cp\u003e可选的\u003ccode class=\"literal\"\u003eWITH\u003c/code\u003e子句为索引指定\u003cem class=\"firstterm\"\u003e存储参数\u003c/em\u003e。每一种索引方法都有其各自允许的存储参数集合。\u003c/p\u003e\u003cp\u003eB-树、hash、GiST 和 SP-GiST 索引方法都接受以下参数：\u003c/p\u003e\u003cdiv class=\"variablelist\"\u003e\u003cdl class=\"variablelist\"\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003efillfactor\u003c/code\u003e (\u003ccode class=\"type\"\u003einteger\u003c/code\u003e) \u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e控制索引方法尝试将索引页填充到多满。对于 B-树，在初始构建索引时，以及在右侧扩展索引（加入新的最大键值）时，叶子页都会填充到这一百分比。如果页面随后变成全满，就会发生分裂，从而导致磁盘上的索引结构碎片化。B-树默认使用 90 的填充因子，但也可以选择 10 到 100 之间的任意整数值。\u003c/p\u003e\u003cp\u003e对预计会有大量插入和/或更新的表，在\u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e 时为 B-树索引设置较低的填充因子会有好处（即在向表批量装载数据之后）。50 到 90 范围内的值可以有效地\u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003e平滑\u003c/span\u003e”\u003c/span\u003eB-树索引生命周期早期页面分裂的\u003cspan class=\"emphasis\"\u003e\u003cem\u003e速率\u003c/em\u003e\u003c/span\u003e（这样降低填充因子甚至可能减少页面分裂的绝对数量，不过这一效果高度依赖工作负载）。\u003ca href=\"/docs/18/btree.html#BTREE-DELETION\" title=\"65.1.4.2. 自底向上索引删除\"\u003e第 65.1.4.2 节\u003c/a\u003e中描述的 B-树自底向上索引删除技术依赖于页面上有一些\u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003e额外\u003c/span\u003e”\u003c/span\u003e空间来存储\u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003e额外\u003c/span\u003e”\u003c/span\u003e的元组版本，因此也会受到填充因子影响（不过通常影响不大）。\u003c/p\u003e\u003cp\u003e在某些其他特定情况下，在\u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e时将填充因子提高到 100 可能有助于最大化空间利用率。只有在完全确定该表是静态的（即永远不会受到插入或更新影响）时，才应考虑这样做。否则，将填充因子设为 100 有\u003cspan class=\"emphasis\"\u003e\u003cem\u003e损害\u003c/em\u003e\u003c/span\u003e性能的风险：即便只有少量更新或插入，也会导致页面突然大量分裂。\u003c/p\u003e\u003cp\u003e其他索引方法以不同但大致类似的方式使用填充因子；默认填充因子因方法而异。\u003c/p\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003cp\u003eB-树索引还接受以下参数：\u003c/p\u003e\u003cdiv class=\"variablelist\"\u003e\u003cdl class=\"variablelist\"\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003ededuplicate_items\u003c/code\u003e (\u003ccode class=\"type\"\u003eboolean\u003c/code\u003e) \u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e控制是否使用\u003ca href=\"/docs/18/btree.html#BTREE-DEDUPLICATION\" title=\"65.1.4.3. 去重\"\u003e第 65.1.4.3 节\u003c/a\u003e中描述的 B-树去重技术。设置为\u003ccode class=\"literal\"\u003eON\u003c/code\u003e或\u003ccode class=\"literal\"\u003eOFF\u003c/code\u003e可启用或禁用该优化。（\u003ccode class=\"literal\"\u003eON\u003c/code\u003e和\u003ccode class=\"literal\"\u003eOFF\u003c/code\u003e的其他拼写形式也被接受，如\u003ca href=\"/docs/18/config-setting.html\" title=\"19.1. 设置参数\"\u003e第 19.1 节\u003c/a\u003e所述。）默认值为\u003ccode class=\"literal\"\u003eON\u003c/code\u003e。\u003c/p\u003e\u003cdiv class=\"note\"\u003e\u003ch3\u003e注意\u003c/h3\u003e\u003cp\u003e通过\u003ccode class=\"command\"\u003eALTER INDEX\u003c/code\u003e关闭\u003ccode class=\"literal\"\u003ededuplicate_items\u003c/code\u003e 可以防止将来的插入触发去重，但这本身不会让现有倒排列表元组改用标准的元组表示。\u003c/p\u003e\u003c/div\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003cp\u003eGiST 索引还接受以下参数：\u003c/p\u003e\u003cdiv class=\"variablelist\"\u003e\u003cdl class=\"variablelist\"\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003ebuffering\u003c/code\u003e (\u003ccode class=\"type\"\u003eenum\u003c/code\u003e) \u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e控制是否使用\u003ca href=\"/docs/18/gist.html#GIST-BUFFERING-BUILD\" title=\"65.2.4.1. GiST 索引构建方法\"\u003e第 65.2.4.1 节\u003c/a\u003e中描述的缓冲构建技术来构建索引。设置为\u003ccode class=\"literal\"\u003eOFF\u003c/code\u003e时禁用缓冲构建，设置为 \u003ccode class=\"literal\"\u003eON\u003c/code\u003e时启用，设置为\u003ccode class=\"literal\"\u003eAUTO\u003c/code\u003e时初始为禁用，但一旦索引大小达到\u003ca href=\"/docs/18/runtime-config-query.html#GUC-EFFECTIVE-CACHE-SIZE\"\u003eeffective_cache_size\u003c/a\u003e，就会在运行过程中启用。默认值为\u003ccode class=\"literal\"\u003eAUTO\u003c/code\u003e。注意，如果可以使用排序构建，则除非指定\u003ccode class=\"literal\"\u003ebuffering=ON\u003c/code\u003e，否则会改用排序构建而不是缓冲构建。\u003c/p\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003cp\u003eGIN 索引接受以下参数：\u003c/p\u003e\u003cdiv class=\"variablelist\"\u003e\u003cdl class=\"variablelist\"\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003efastupdate\u003c/code\u003e (\u003ccode class=\"type\"\u003eboolean\u003c/code\u003e) \u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e控制\u003ca href=\"/docs/18/gin.html#GIN-FAST-UPDATE\" title=\"65.4.4.1. GIN 快速更新技术\"\u003e第 65.4.4.1 节\u003c/a\u003e中描述的快速更新技术的使用。\u003ccode class=\"literal\"\u003eON\u003c/code\u003e 启用快速更新，\u003ccode class=\"literal\"\u003eOFF\u003c/code\u003e 禁用快速更新。默认值为\u003ccode class=\"literal\"\u003eON\u003c/code\u003e。\u003c/p\u003e\u003cdiv class=\"note\"\u003e\u003ch3\u003e注意\u003c/h3\u003e\u003cp\u003e通过\u003ccode class=\"command\"\u003eALTER INDEX\u003c/code\u003e关闭\u003ccode class=\"literal\"\u003efastupdate\u003c/code\u003e 会阻止后续插入进入待处理索引项列表，但这本身不会将现有条目移出待处理列表。之后可能需要对该表执行\u003ccode class=\"command\"\u003eVACUUM\u003c/code\u003e，或调用 \u003ccode class=\"function\"\u003egin_clean_pending_list\u003c/code\u003e函数，以确保待处理列表被清空。\u003c/p\u003e\u003c/div\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003cdiv class=\"variablelist\"\u003e\u003cdl class=\"variablelist\"\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003egin_pending_list_limit\u003c/code\u003e (\u003ccode class=\"type\"\u003einteger\u003c/code\u003e) \u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e为该索引覆盖\u003ca href=\"/docs/18/runtime-config-client.html#GUC-GIN-PENDING-LIST-LIMIT\"\u003egin_pending_list_limit\u003c/a\u003e的全局设置。该值以千字节为单位。\u003c/p\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003cp\u003e\u003cacronym\u003eBRIN\u003c/acronym\u003e 索引接受以下参数：\u003c/p\u003e\u003cdiv class=\"variablelist\"\u003e\u003cdl class=\"variablelist\"\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003epages_per_range\u003c/code\u003e (\u003ccode class=\"type\"\u003einteger\u003c/code\u003e) \u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e定义每个\u003cacronym\u003eBRIN\u003c/acronym\u003e索引项对应的一个块范围由多少个表块组成（详见\u003ca href=\"/docs/18/brin.html#BRIN-INTRO\" title=\"65.5.1. 简介\"\u003e第 65.5.1 节\u003c/a\u003e）。默认值为\u003ccode class=\"literal\"\u003e128\u003c/code\u003e。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eautosummarize\u003c/code\u003e (\u003ccode class=\"type\"\u003eboolean\u003c/code\u003e) \u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e定义当在下一页范围检测到插入时，是否为前一页范围排队执行一次范围摘要操作（详见\u003ca href=\"/docs/18/brin.html#BRIN-OPERATION\" title=\"65.5.1.1. 索引维护\"\u003e第 65.5.1.1 节\u003c/a\u003e）。默认值为\u003ccode class=\"literal\"\u003eoff\u003c/code\u003e。\u003c/p\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv class=\"refsect2\"\u003e\u003ch3\u003e并发构建索引\u003c/h3\u003e\u003cp\u003e创建索引可能会干扰数据库的正常运行。通常 \u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e会锁住要建立索引的表，阻止其写入，并通过一次扫描完成整个索引构建。其他事务仍可读取该表，但如果它们试图在表中插入、更新或删除行，就会阻塞直到索引构建完成。如果系统是在线生产数据库，这可能产生严重影响。对非常大的表建立索引可能需要很多小时，即便是较小的表，索引构建也可能在一段对生产系统而言不可接受的时间内阻止写入者操作。\u003c/p\u003e\u003cp\u003e\u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e支持在不阻止写入的情况下构建索引。这种方法通过在\u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e中指定 \u003ccode class=\"literal\"\u003eCONCURRENTLY\u003c/code\u003e选项来启用。使用该选项时，\u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e必须对该表执行两次扫描，此外还必须等待所有现有、可能修改或使用该索引的事务结束。因此，这种方法比标准索引构建需要更多总工作量，完成时间也明显更长。不过，由于它允许在构建索引期间继续进行正常操作，所以这种方法适合在生产环境中新增索引。当然，创建索引带来的额外 CPU 和 I/O 负载也可能拖慢其他操作。\u003c/p\u003e\u003cp\u003e在并发索引构建中，索引实际上会先在一个事务中作为\u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003e无效\u003c/span\u003e”\u003c/span\u003e索引录入系统目录，然后在另外两个事务中执行两次表扫描。每次表扫描之前，索引构建都必须等待已修改该表的现有事务结束。第二次扫描之后，索引构建还必须等待所有持有早于第二次扫描的快照（参见\u003ca href=\"/docs/18/mvcc.html\" title=\"第 13 章 并发控制\"\u003e第 13 章\u003c/a\u003e）的事务结束；如果相关索引是部分索引，或包含并非简单列引用的列，这还包括其他表上并发索引构建任何阶段所使用的事务。最后，索引才能被标记为\u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003e有效\u003c/span\u003e”\u003c/span\u003e并可供使用，而 \u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e命令随之结束。即便如此，索引也未必能立即用于查询：最坏情况下，只要仍存在早于索引构建开始的事务，它就不能被使用。\u003c/p\u003e\u003cp\u003e如果在扫描表时出现问题，例如死锁或唯一索引中的唯一性违反，\u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e命令将失败，但会留下一个\u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003e无效\u003c/span\u003e”\u003c/span\u003e索引。这个索引在查询时会被忽略，因为它可能不完整；但它仍会带来更新开销。\u003cspan class=\"application\"\u003epsql\u003c/span\u003e \u003ccode class=\"command\"\u003e\\d\u003c/code\u003e命令会将这样的索引报告为 \u003ccode class=\"literal\"\u003eINVALID\u003c/code\u003e：\u003c/p\u003e\u003cpre class=\"programlisting\"\u003epostgres=# \\d tab\n       Table \"public.tab\"\n Column |  Type   | Collation | Nullable | Default\n--------+---------+-----------+----------+---------\n col    | integer |           |          |\nIndexes:\n    \"idx\" btree (col) INVALID\n\u003c/pre\u003e\u003cp\u003e在这种情况下，推荐的恢复方法是删除该索引，然后再次尝试执行 \u003ccode class=\"command\"\u003eCREATE INDEX CONCURRENTLY\u003c/code\u003e。（另一种做法是用 \u003ccode class=\"command\"\u003eREINDEX INDEX CONCURRENTLY\u003c/code\u003e重建索引。）\u003c/p\u003e\u003cp\u003e并发构建唯一索引时的另一项注意事项是，在第二次表扫描开始时，唯一性约束就已经开始对其他事务生效了。这意味着在该索引可供使用之前，其他查询就可能报告约束违规，甚至在索引构建最终失败的情况下也是如此。另外，如果第二次扫描确实失败了，那个\u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003e无效\u003c/span\u003e”\u003c/span\u003e索引之后仍会继续强制执行其唯一性约束。\u003c/p\u003e\u003cp\u003e也支持并发构建表达式索引和部分索引。计算这些表达式时发生的错误，可能导致与上文所述唯一性约束违规类似的行为。\u003c/p\u003e\u003cp\u003e普通索引构建允许在同一张表上同时进行其他普通索引构建，但一张表在同一时刻只能发生一次并发索引构建。无论哪种情况，在索引构建期间都不允许修改该表的模式。另一个区别是，普通\u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e 命令可以在事务块内执行，而\u003ccode class=\"command\"\u003eCREATE INDEX CONCURRENTLY\u003c/code\u003e 不能。\u003c/p\u003e\u003cp\u003e当前不支持对分区表的索引进行并发构建。不过，可以分别在每个分区上并发构建索引，最后再以非并发方式创建分区索引，从而缩短分区表写入被阻止的时间。在这种情况下，构建分区索引只是元数据操作。\u003c/p\u003e\u003c/div\u003e","key":"parameters","title":"参数"},{"html":"\u003cp\u003e关于索引何时能被使用、何时不被使用以及什么情况下它们有用的信息请见\u003ca href=\"/docs/18/indexes.html\" title=\"第 11 章 索引\"\u003e第 11 章\u003c/a\u003e。\u003c/p\u003e\u003cp\u003e当前，只有 B-树、GiST、GIN 和 BRIN 索引方法支持多键列索引。能否拥有多个键列，与能否向索引添加\u003ccode class=\"literal\"\u003eINCLUDE\u003c/code\u003e列无关。索引最多可以有 32 列，包括\u003ccode class=\"literal\"\u003eINCLUDE\u003c/code\u003e列。（可以在构建\u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e时修改这个限制）。当前只有 B-树支持唯一索引。\u003c/p\u003e\u003cp\u003e可以为索引中的每一列指定一个带可选参数的\u003cem class=\"firstterm\"\u003e操作符类\u003c/em\u003e。操作符类标识该索引在该列上要使用的操作符。例如，一个四字节整数上的 B-树索引会使用\u003ccode class=\"literal\"\u003eint4_ops\u003c/code\u003e类；这个操作符类包含用于四字节整数的比较函数。实际上，列数据类型的默认操作符类通常就足够了。引入操作符类的主要原因在于，对于某些数据类型，可能存在不止一种有意义的排序方式。例如，可能需要按绝对值或实部对复数数据类型排序。要做到这一点，可以为该数据类型定义两个操作符类，然后在创建索引时选择合适的类。关于操作符类的更多信息请见\u003ca href=\"/docs/18/indexes-opclass.html\" title=\"11.10. 操作符类和操作符族\"\u003e第 11.10 节\u003c/a\u003e以及\u003ca href=\"/docs/18/xindex.html\" title=\"36.16. 索引扩展接口\"\u003e第 36.16 节\u003c/a\u003e。\u003c/p\u003e\u003cp\u003e当在分区表上调用\u003ccode class=\"literal\"\u003eCREATE INDEX\u003c/code\u003e时，默认行为是递归到所有分区，以确保它们都拥有匹配的索引。系统首先检查每个分区是否已经存在等效索引；如果存在，该索引会作为正在创建索引的分区索引附接到其上，而被创建的索引将成为其父索引。若不存在匹配索引，则会创建一个新索引并自动附着；每个分区中新索引的名称会按命令中未指定索引名时的规则确定。如果指定\u003ccode class=\"literal\"\u003eONLY\u003c/code\u003e选项，则不进行递归，且该索引会被标记为无效。（一旦所有分区都获得匹配索引，\u003ccode class=\"command\"\u003eALTER INDEX ... ATTACH PARTITION\u003c/code\u003e会将该索引标记为有效。）不过请注意，将来使用 \u003ccode class=\"command\"\u003eCREATE TABLE ... PARTITION OF\u003c/code\u003e创建的任何分区都会自动拥有匹配索引，无论是否指定了\u003ccode class=\"literal\"\u003eONLY\u003c/code\u003e。\u003c/p\u003e\u003cp\u003e对于支持有序扫描的索引方法（当前只有 B-树），可以指定可选子句 \u003ccode class=\"literal\"\u003eASC\u003c/code\u003e、\u003ccode class=\"literal\"\u003eDESC\u003c/code\u003e、\u003ccode class=\"literal\"\u003eNULLS FIRST\u003c/code\u003e 和/或\u003ccode class=\"literal\"\u003eNULLS LAST\u003c/code\u003e来修改索引的排序顺序。由于有序索引可以向前或向后扫描，因此创建单列\u003ccode class=\"literal\"\u003eDESC\u003c/code\u003e索引通常并无用处 — 常规索引已经提供了这种排序顺序。这些选项的价值在于可以创建与混合排序查询所要求顺序相匹配的多列索引，例如 \u003ccode class=\"literal\"\u003eSELECT ... ORDER BY x ASC, y DESC\u003c/code\u003e。如果需要在依靠索引避免排序步骤的查询中支持\u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003e空值排在低位\u003c/span\u003e”\u003c/span\u003e，而不是默认的\u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003e空值排在高位\u003c/span\u003e”\u003c/span\u003e行为，那么\u003ccode class=\"literal\"\u003eNULLS\u003c/code\u003e选项就很有用。\u003c/p\u003e\u003cp\u003e系统定期收集表中所有列的统计信息。新创建的非表达式索引可以立即使用这些统计信息来确定索引的有用性。对于新的表达式索引，需要运行 \u003ca href=\"/docs/18/sql-analyze.html\" title=\"ANALYZE\"\u003e\u003ccode class=\"command\"\u003eANALYZE\u003c/code\u003e\u003c/a\u003e 或等待\u003ca href=\"/docs/18/routine-vacuuming.html#AUTOVACUUM\" title=\"24.1.6. 自动清理守护进程\"\u003e自动清理守护进程\u003c/a\u003e分析表以生成这些索引的统计信息。\u003c/p\u003e\u003cp\u003e在 \u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e 执行期间，\u003ca href=\"/docs/18/runtime-config-client.html#GUC-SEARCH-PATH\"\u003esearch_path\u003c/a\u003e会被临时设置为 \u003ccode class=\"literal\"\u003epg_catalog, pg_temp\u003c/code\u003e。\u003c/p\u003e\u003cp\u003e对于大多数索引方法，索引的创建速度取决于\u003ca href=\"/docs/18/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM\"\u003emaintenance_work_mem\u003c/a\u003e的设置。较大的值将会减少索引创建所需的时间，当然不要把它设置得超过实际可用的内存量（那会迫使机器进行交换）。\u003c/p\u003e\u003cp\u003e\u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e可以在构建索引时利用多个 CPU，以便更快处理表中的行。这项特性被称为\u003cem class=\"firstterm\"\u003e并行索引构建\u003c/em\u003e。对于支持并行构建索引的索引方法（当前为 B-树、GIN 和 BRIN），\u003ccode class=\"varname\"\u003emaintenance_work_mem\u003c/code\u003e指定每次索引构建操作整体最多可使用的内存量，而不管启动了多少工作者进程。通常，代价模型会自动决定是否需要请求工作者进程，以及请求多少个。\u003c/p\u003e\u003cp\u003e增加\u003ccode class=\"varname\"\u003emaintenance_work_mem\u003c/code\u003e可能会让并行索引构建受益，而等效的串行索引构建则几乎看不到收益。注意，\u003ccode class=\"varname\"\u003emaintenance_work_mem\u003c/code\u003e可能会影响所请求工作者进程的数量，因为每个并行工作者都必须至少从总的 \u003ccode class=\"varname\"\u003emaintenance_work_mem\u003c/code\u003e预算中分得\u003ccode class=\"literal\"\u003e32MB\u003c/code\u003e。领导者进程也必须保留\u003ccode class=\"literal\"\u003e32MB\u003c/code\u003e。增加\u003ca href=\"/docs/18/runtime-config-resource.html#GUC-MAX-PARALLEL-MAINTENANCE-WORKERS\"\u003emax_parallel_maintenance_workers\u003c/a\u003e可能允许使用更多工作者，从而减少索引创建所需时间，前提是索引构建尚未受到 I/O 限制。当然，还应当有足够的、原本会闲置的 CPU 容量。\u003c/p\u003e\u003cp\u003e通过\u003ca href=\"/docs/18/sql-altertable.html\" title=\"ALTER TABLE\"\u003e\u003ccode class=\"command\"\u003eALTER TABLE\u003c/code\u003e\u003c/a\u003e 为\u003ccode class=\"literal\"\u003eparallel_workers\u003c/code\u003e设置一个值，可以直接控制 \u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e对该表会请求多少并行工作者进程。这会完全绕过代价模型，也使\u003ccode class=\"varname\"\u003emaintenance_work_mem\u003c/code\u003e不再影响所请求的并行工作者数量。通过\u003ccode class=\"command\"\u003eALTER TABLE\u003c/code\u003e将 \u003ccode class=\"literal\"\u003eparallel_workers\u003c/code\u003e设置为 0，将在所有情况下禁用该表上的并行索引构建。\u003c/p\u003e\u003cdiv class=\"tip\"\u003e\u003ch3\u003e提示\u003c/h3\u003e\u003cp\u003e在把\u003ccode class=\"literal\"\u003eparallel_workers\u003c/code\u003e作为索引构建调优的一部分进行设置后，可能需要将其重置。这样可以避免无意间改变查询计划，因为 \u003ccode class=\"literal\"\u003eparallel_workers\u003c/code\u003e会影响\u003cspan class=\"emphasis\"\u003e\u003cem\u003e所有\u003c/em\u003e\u003c/span\u003e并行表扫描。\u003c/p\u003e\u003c/div\u003e\u003cp\u003e虽然带有\u003ccode class=\"literal\"\u003eCONCURRENTLY\u003c/code\u003e选项的\u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e 在没有特殊限制的情况下支持并行构建，但实际上只有第一次表扫描会以并行方式执行。\u003c/p\u003e\u003cp\u003e使用\u003ca href=\"/docs/18/sql-dropindex.html\" title=\"DROP INDEX\"\u003e\u003ccode class=\"command\"\u003eDROP INDEX\u003c/code\u003e\u003c/a\u003e 可以移除索引。\u003c/p\u003e\u003cp\u003e和任何长时间运行的事务一样，在某个表上执行\u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e 会影响在其他任何表上并发执行\u003ccode class=\"command\"\u003eVACUUM\u003c/code\u003e时哪些元组可以被移除。\u003c/p\u003e\u003cp\u003e早期版本的\u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e还提供过一种 R-tree 索引方法。该方法已经被移除，因为它相对于 GiST 方法并无明显优势。如果指定了\u003ccode class=\"literal\"\u003eUSING rtree\u003c/code\u003e，\u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e 会将其解释为\u003ccode class=\"literal\"\u003eUSING gist\u003c/code\u003e，以简化旧数据库向 GiST 的转换。\u003c/p\u003e\u003cp\u003e每个运行\u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e的后端将在 \u003ccode class=\"structname\"\u003epg_stat_progress_create_index\u003c/code\u003e视图中报告其进度。有关详细信息，请参见\u003ca href=\"/docs/18/progress-reporting.html#CREATE-INDEX-PROGRESS-REPORTING\" title=\"27.4.4. CREATE INDEX 进度报告\"\u003e第 27.4.4 节\u003c/a\u003e。\u003c/p\u003e","key":"notes","title":"注解"},{"html":"\u003cp\u003e要在表\u003ccode class=\"literal\"\u003efilms\u003c/code\u003e的列\u003ccode class=\"literal\"\u003etitle\u003c/code\u003e上创建一个唯一 B-树索引：\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eCREATE UNIQUE INDEX title_idx ON films (title);\n\u003c/pre\u003e\u003cp\u003e要在表\u003ccode class=\"literal\"\u003efilms\u003c/code\u003e的列\u003ccode class=\"literal\"\u003etitle\u003c/code\u003e上创建一个唯一 B-树索引，并将\u003ccode class=\"literal\"\u003edirector\u003c/code\u003e和\u003ccode class=\"literal\"\u003erating\u003c/code\u003e作为内含列：\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eCREATE UNIQUE INDEX title_idx ON films (title) INCLUDE (director, rating);\n\u003c/pre\u003e\u003cp\u003e要创建一个禁用去重的 B-树索引：\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eCREATE INDEX title_idx ON films (title) WITH (deduplicate_items = off);\n\u003c/pre\u003e\u003cp\u003e要在表达式\u003ccode class=\"literal\"\u003elower(title)\u003c/code\u003e上创建一个索引，以便高效执行不区分大小写的搜索：\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eCREATE INDEX ON films ((lower(title)));\n\u003c/pre\u003e\u003cp\u003e（在这个示例中，索引名称被省略，因此系统会选择一个名字，通常为\u003ccode class=\"literal\"\u003efilms_lower_idx\u003c/code\u003e。）\u003c/p\u003e\u003cp\u003e要创建一个具有非默认排序规则的索引：\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eCREATE INDEX title_idx_german ON films (title COLLATE \"de_DE\");\n\u003c/pre\u003e\u003cp\u003e要创建一个具有非默认空值排序顺序的索引：\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eCREATE INDEX title_idx_nulls_low ON films (title NULLS FIRST);\n\u003c/pre\u003e\u003cp\u003e要创建一个具有非默认填充因子的索引：\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eCREATE UNIQUE INDEX title_idx ON films (title) WITH (fillfactor = 70);\n\u003c/pre\u003e\u003cp\u003e要创建一个禁用快速更新的\u003cacronym\u003eGIN\u003c/acronym\u003e索引：\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eCREATE INDEX gin_idx ON documents_table USING GIN (locations) WITH (fastupdate = off);\n\u003c/pre\u003e\u003cp\u003e要在表\u003ccode class=\"literal\"\u003efilms\u003c/code\u003e的列\u003ccode class=\"literal\"\u003ecode\u003c/code\u003e上创建一个索引，并让该索引驻留在表空间\u003ccode class=\"literal\"\u003eindexspace\u003c/code\u003e中：\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eCREATE INDEX code_idx ON films (code) TABLESPACE indexspace;\n\u003c/pre\u003e\u003cp\u003e要在点属性上创建一个 GiST 索引，以便能够在转换函数的结果上高效地使用 box 操作符：\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eCREATE INDEX pointloc\n    ON points USING gist (box(location,location));\nSELECT * FROM points\n    WHERE box(location,location) \u0026amp;\u0026amp; '(0,0),(1,1)'::box;\n\u003c/pre\u003e\u003cp\u003e要在不阻止对表执行写操作的情况下创建索引：\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eCREATE INDEX CONCURRENTLY sales_quantity_index ON sales_table (quantity);\n\u003c/pre\u003e","key":"examples","title":"示例"},{"html":"\u003cp\u003e\u003ccode class=\"command\"\u003eCREATE INDEX\u003c/code\u003e是 \u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e的语言扩展。SQL 标准中没有关于索引的规定。\u003c/p\u003e","key":"compatibility","title":"兼容性"},{"html":"\u003cspan class=\"simplelist\"\u003e\u003ca href=\"/wiki/sql/alter-index/?v=18\" title=\"ALTER INDEX\"\u003e\u003cspan class=\"refentrytitle\"\u003eALTER INDEX\u003c/span\u003e\u003c/a\u003e, \u003ca href=\"/wiki/sql/drop-index/?v=18\" title=\"DROP INDEX\"\u003e\u003cspan class=\"refentrytitle\"\u003eDROP INDEX\u003c/span\u003e\u003c/a\u003e, \u003ca href=\"/wiki/sql/reindex/?v=18\" title=\"REINDEX\"\u003e\u003cspan class=\"refentrytitle\"\u003eREINDEX\u003c/span\u003e\u003c/a\u003e, \u003ca href=\"/docs/18/progress-reporting.html#CREATE-INDEX-PROGRESS-REPORTING\" title=\"27.4.4. CREATE INDEX 进度报告\"\u003e第 27.4.4 节\u003c/a\u003e\u003c/span\u003e","key":"see_also","title":"另见"}],"sections_same_as":"","synopsis_html":"CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] \u003cem class=\"replaceable\"\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/em\u003e ] ON [ ONLY ] \u003cem class=\"replaceable\"\u003e\u003ccode\u003etable_name\u003c/code\u003e\u003c/em\u003e [ USING \u003cem class=\"replaceable\"\u003e\u003ccode\u003emethod\u003c/code\u003e\u003c/em\u003e ]\n    ( { \u003cem class=\"replaceable\"\u003e\u003ccode\u003ecolumn_name\u003c/code\u003e\u003c/em\u003e | ( \u003cem class=\"replaceable\"\u003e\u003ccode\u003eexpression\u003c/code\u003e\u003c/em\u003e ) } [ COLLATE \u003cem class=\"replaceable\"\u003e\u003ccode\u003ecollation\u003c/code\u003e\u003c/em\u003e ] [ \u003cem class=\"replaceable\"\u003e\u003ccode\u003eopclass\u003c/code\u003e\u003c/em\u003e [ ( \u003cem class=\"replaceable\"\u003e\u003ccode\u003eopclass_parameter\u003c/code\u003e\u003c/em\u003e = \u003cem class=\"replaceable\"\u003e\u003ccode\u003evalue\u003c/code\u003e\u003c/em\u003e [, ... ] ) ] ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] )\n    [ INCLUDE ( \u003cem class=\"replaceable\"\u003e\u003ccode\u003ecolumn_name\u003c/code\u003e\u003c/em\u003e [, ...] ) ]\n    [ NULLS [ NOT ] DISTINCT ]\n    [ WITH ( \u003cem class=\"replaceable\"\u003e\u003ccode\u003estorage_parameter\u003c/code\u003e\u003c/em\u003e [= \u003cem class=\"replaceable\"\u003e\u003ccode\u003evalue\u003c/code\u003e\u003c/em\u003e] [, ... ] ) ]\n    [ TABLESPACE \u003cem class=\"replaceable\"\u003e\u003ccode\u003etablespace_name\u003c/code\u003e\u003c/em\u003e ]\n    [ WHERE \u003cem class=\"replaceable\"\u003e\u003ccode\u003epredicate\u003c/code\u003e\u003c/em\u003e ]","synopsis_text":"CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] name ] ON [ ONLY ] table_name [ USING method ]\n( { column_name | ( expression ) } [ COLLATE collation ] [ opclass [ ( opclass_parameter = value [, ... ] ) ] ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] )\n[ INCLUDE ( column_name [, ...] ) ]\n[ NULLS [ NOT ] DISTINCT ]\n[ WITH ( storage_parameter [= value] [, ... ] ) ]\n[ TABLESPACE tablespace_name ]\n[ WHERE predicate ]"}},"RequestedLocale":"zh-Hans","Fallback":false,"Versions":["10","11","12","13","14","15","16","17","18","19","20","6.4","6.5","7.0","7.1","7.2","7.3","7.4","8.0","8.1","8.2","8.3","8.4","9.0","9.1","9.2","9.3","9.4","9.5","9.6"],"Locales":["en","zh-Hans"],"Signatures":null,"Spellings":null,"SQLState":null,"Evidence":null}
