diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index 4851bc2e24..fffb79f713 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -3753,15 +3753,16 @@ SCRAM-SHA-256$<iteration count>:&l int2 The total number of columns in the index (duplicates - pg_class.relnatts). This number includes both key and included attributes. + pg_class.relnatts); this number includes both key and included attributes indnkeyatts int2 - The number of key columns in the index. "Key columns" are ordinary - index columns (as opposed to "included" columns). + The number of key columns in the index, + not counting any included columns, which are + merely stored and do not participate in the index semantics @@ -3867,7 +3868,8 @@ SCRAM-SHA-256$<iteration count>:&l This is an array of indnatts values that indicate which table columns this index indexes. For example a value of 1 3 would mean that the first and the third table - columns make up the index key. A zero in this array indicates that the + columns make up the index entries. Key columns come before non-key + (included) columns. A zero in this array indicates that the corresponding index attribute is an expression over the table columns, rather than a simple column reference. @@ -3878,9 +3880,10 @@ SCRAM-SHA-256$<iteration count>:&l oidvector pg_collation.oid - For each column in the index key, this contains the OID of the - collation to use for the index, or zero if the column is not - of a collatable data type. + For each column in the index key + (indnkeyatts values), this contains the OID + of the collation to use for the index, or zero if the column is not of + a collatable data type. @@ -3889,8 +3892,9 @@ SCRAM-SHA-256$<iteration count>:&l oidvector pg_opclass.oid - For each column in the index key, this contains the OID of - the operator class to use. See + For each column in the index key + (indnkeyatts values), this contains the OID + of the operator class to use. See pg_opclass for details. @@ -3900,7 +3904,7 @@ SCRAM-SHA-256$<iteration count>:&l int2vector - This is an array of indnatts values that + This is an array of indnkeyatts values that store per-column flag bits. The meaning of the bits is defined by the index's access method. diff --git a/doc/src/sgml/indexam.sgml b/doc/src/sgml/indexam.sgml index 24c3405f91..c72c522175 100644 --- a/doc/src/sgml/indexam.sgml +++ b/doc/src/sgml/indexam.sgml @@ -112,10 +112,10 @@ typedef struct IndexAmRoutine bool ampredlocks; /* does AM support parallel scan? */ bool amcanparallel; - /* type of data stored in index, or InvalidOid if variable */ - Oid amkeytype; /* does AM support columns included with clause INCLUDE? */ bool amcaninclude; + /* type of data stored in index, or InvalidOid if variable */ + Oid amkeytype; /* interface functions */ ambuild_function ambuild; @@ -987,8 +987,9 @@ amparallelrescan (IndexScanDesc scan); using unique indexes, which are indexes that disallow multiple entries with identical keys. An access method that supports this feature sets amcanunique true. - (At present, only b-tree supports it.) Columns listed in the - INCLUDE clause are not used to enforce uniqueness. + (At present, only b-tree supports it.) Columns listed in the + INCLUDE clause are not considered when enforcing + uniqueness. diff --git a/doc/src/sgml/indices.sgml b/doc/src/sgml/indices.sgml index 14a1aa56cb..a57c5e2e1f 100644 --- a/doc/src/sgml/indices.sgml +++ b/doc/src/sgml/indices.sgml @@ -639,7 +639,7 @@ CREATE INDEX test3_desc_index ON test3 (id DESC NULLS LAST); or the uniqueness of the combined values of more than one column. CREATE UNIQUE INDEX name ON table (column , ...) -[ INCLUDE (column , ...) ]; + INCLUDE (column , ...) ; Currently, only B-tree indexes can be declared unique. @@ -648,9 +648,9 @@ CREATE UNIQUE INDEX name ON tableINCLUDE clause aren't used to enforce constraints - (UNIQUE, PRIMARY KEY, etc). + indexed columns are equal. Columns listed in + the INCLUDE clause, if any, aren't considered when + determining whether index entries are equal. diff --git a/doc/src/sgml/ref/create_index.sgml b/doc/src/sgml/ref/create_index.sgml index 91692325a5..3c1223b324 100644 --- a/doc/src/sgml/ref/create_index.sgml +++ b/doc/src/sgml/ref/create_index.sgml @@ -149,25 +149,28 @@ CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] The optional INCLUDE clause specifies a - list of columns which will be included as a non-key part in the index. - Columns listed in this clause cannot also be present as index key columns. - The INCLUDE columns exist solely to - allow more queries to benefit from index-only scans - by including the values of the specified columns in the index. These values - would otherwise have to be obtained by reading the table's heap. + list of columns which will be included in the index + as non-key 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. - In UNIQUE indexes, uniqueness is only enforced - for key columns. Columns listed in the INCLUDE - clause have no effect on uniqueness enforcement. Other constraints - (PRIMARY KEY and EXCLUDE) work - the same way. + It'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. Columns listed in the INCLUDE clause don't need - appropriate operator classes; the clause can contain non-key index + appropriate operator classes; the clause can include columns whose data types don't have operator classes defined for a given access method. @@ -181,15 +184,8 @@ CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] INCLUDE clause are included in leaf tuples which - are linked to the heap tuples, but are not included into pivot tuples - used for tree navigation. Therefore, moving columns from the list of - key columns to the INCLUDE clause can slightly - reduce index size and improve the tree branching factor. - - - - Indexes with columns listed in the INCLUDE clause - are also called covering indexes. + correspond to heap tuples, but are not included in upper-level + index entries used for tree navigation. @@ -376,7 +372,7 @@ CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] - + Functional indexes are used frequently for the case where the function returns a subset of the argument. Examples of this would be accessing @@ -789,8 +785,8 @@ CREATE UNIQUE INDEX title_idx ON films (title); To create a unique B-tree index on the column title - and included columns director and rating - in the table films: + with included columns director + and rating in the table films: CREATE UNIQUE INDEX title_idx ON films (title) INCLUDE (director, rating); diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml index f74b9840a0..d936de3f23 100644 --- a/doc/src/sgml/ref/create_table.sgml +++ b/doc/src/sgml/ref/create_table.sgml @@ -869,9 +869,8 @@ WITH ( MODULUS numeric_literal, REM one or more columns on which the uniqueness is not enforced. Note that although the constraint is not enforced on the included columns, it still depends on them. Consequently, some operations on these columns - (e.g. DROP COLUMN) can cause cascade constraint and - index deletion. See paragraph about INCLUDE in - for more information. + (e.g. DROP COLUMN) can cause cascaded constraint and + index deletion. @@ -916,9 +915,8 @@ WITH ( MODULUS numeric_literal, REM of columns to be specified which will be included in the non-key portion of the index. Although uniqueness is not enforced on the included columns, the constraint still depends on them. Consequently, some operations on the - included columns (e.g. DROP COLUMN) can cause cascade - constraint and index deletion. See paragraph about INCLUDE - in for more information. + included columns (e.g. DROP COLUMN) can cause cascaded + constraint and index deletion. diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 0053832195..b9dad9672e 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -369,11 +369,6 @@ DefineIndex(Oid relationId, Snapshot snapshot; int i; - if (list_intersection(stmt->indexParams, stmt->indexIncludingParams) != NIL) - ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("included columns must not intersect with key columns"))); - /* * count key attributes in index */ @@ -596,7 +591,7 @@ DefineIndex(Oid relationId, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("access method \"%s\" does not support unique indexes", accessMethodName))); - if (list_length(stmt->indexIncludingParams) > 0 && !amRoutine->amcaninclude) + if (stmt->indexIncludingParams != NIL && !amRoutine->amcaninclude) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("access method \"%s\" does not support included columns", diff --git a/src/test/regress/expected/index_including.out b/src/test/regress/expected/index_including.out index ee976994a4..48bec3bf77 100644 --- a/src/test/regress/expected/index_including.out +++ b/src/test/regress/expected/index_including.out @@ -7,17 +7,17 @@ -- Regular index with included columns CREATE TABLE tbl_include_reg (c1 int, c2 int, c3 int, c4 box); INSERT INTO tbl_include_reg SELECT x, 2*x, 3*x, box('4,4,4,4') FROM generate_series(1,10) AS x; -CREATE INDEX tbl_include_reg_idx ON tbl_include_reg using btree (c1, c2) INCLUDE (c3,c4); --- must fail because of intersection of key and included columns -CREATE INDEX tbl_include_reg_idx ON tbl_include_reg using btree (c1, c2) INCLUDE (c1,c3); -ERROR: included columns must not intersect with key columns +CREATE INDEX tbl_include_reg_idx ON tbl_include_reg (c1, c2) INCLUDE (c3, c4); +-- duplicate column is pretty pointless, but we allow it anyway +CREATE INDEX ON tbl_include_reg (c1, c2) INCLUDE (c1, c3); SELECT pg_get_indexdef(i.indexrelid) FROM pg_index i JOIN pg_class c ON i.indexrelid = c.oid WHERE i.indrelid = 'tbl_include_reg'::regclass ORDER BY c.relname; - pg_get_indexdef --------------------------------------------------------------------------------------------------- + pg_get_indexdef +--------------------------------------------------------------------------------------------------------------- + CREATE INDEX tbl_include_reg_c1_c2_c11_c3_idx ON public.tbl_include_reg USING btree (c1, c2) INCLUDE (c1, c3) CREATE INDEX tbl_include_reg_idx ON public.tbl_include_reg USING btree (c1, c2) INCLUDE (c3, c4) -(1 row) +(2 rows) -- Unique index and unique constraint CREATE TABLE tbl_include_unique1 (c1 int, c2 int, c3 int, c4 box); diff --git a/src/test/regress/sql/index_including.sql b/src/test/regress/sql/index_including.sql index b59adeb845..2d833fc9f7 100644 --- a/src/test/regress/sql/index_including.sql +++ b/src/test/regress/sql/index_including.sql @@ -8,9 +8,9 @@ -- Regular index with included columns CREATE TABLE tbl_include_reg (c1 int, c2 int, c3 int, c4 box); INSERT INTO tbl_include_reg SELECT x, 2*x, 3*x, box('4,4,4,4') FROM generate_series(1,10) AS x; -CREATE INDEX tbl_include_reg_idx ON tbl_include_reg using btree (c1, c2) INCLUDE (c3,c4); --- must fail because of intersection of key and included columns -CREATE INDEX tbl_include_reg_idx ON tbl_include_reg using btree (c1, c2) INCLUDE (c1,c3); +CREATE INDEX tbl_include_reg_idx ON tbl_include_reg (c1, c2) INCLUDE (c3, c4); +-- duplicate column is pretty pointless, but we allow it anyway +CREATE INDEX ON tbl_include_reg (c1, c2) INCLUDE (c1, c3); SELECT pg_get_indexdef(i.indexrelid) FROM pg_index i JOIN pg_class c ON i.indexrelid = c.oid WHERE i.indrelid = 'tbl_include_reg'::regclass ORDER BY c.relname;