Global indexing is an indexing technique for partitioned tables. You can create global indexes on partitioned tables by using non-partition keys. Global indexes can provide unique constraints.
Syntax
CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] name ] ON [ ONLY ] table_name [ USING method ]
( { column_name | ( expression ) } [ COLLATE collation ] [ opclass [ ( opclass_parameter = value [, ... ] ) ] ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] )
[ INCLUDE ( column_name [, ...] ) ]
[ WITH ( storage_parameter [= value] [, ... ] ) ]
[ GLOBAL/LOCAL ]
[ TABLESPACE tablespace_name ]
[ WHERE predicate ]
Description
To create a global index, you must specify the
GLOBAL
keyword instead of theLOCAL
keyword in the CREATE INDEX statement.If you do not specify the GLOBAL or LOCAL keyword, a local index is created by default.
You can specify CONCURRENTLY in a CREATE INDEX statement that creates a global index.
You cannot create global indexes for non-partitioned tables or the child tables of partitioned tables.
You cannot create global indexes based on expressions.
You cannot create global indexes based on the partition key columns of partitioned tables.
Global indexes provide the following benefits:
Global indexes can provide unique constraints on the non-partition key columns of partitioned tables.
Global indexes are created for partitioned tables by using non-partition key columns. This allows global indexes to accelerate queries on partitioned tables in scenarios in which no partition keys are specified.
You can use the cross-node parallel execution feature to accelerate the process of creating global indexes of B-tree indexes. For more information, see Accelerate index creation.
Examples
In the following examples, a table is partitioned by time. Partitions are created on a regular basis to replace previous partitions.
CREATE TABLE partition_range (
id integer,
a int,
b int,
created_date timestamp without time zone
)
PARTITION BY RANGE (created_date);
CREATE TABLE partition_range_part01 (
id integer,
a int,
b int,
created_date timestamp without time zone
);
ALTER TABLE ONLY partition_range ATTACH PARTITION partition_range_part01 FOR VALUES FROM (MINVALUE) TO ('2020-01-01 00:00:00');
CREATE TABLE partition_range_part02 (
id integer,
a int,
b int,
created_date timestamp without time zone
);
ALTER TABLE ONLY partition_range ATTACH PARTITION partition_range_part02 FOR VALUES FROM ('2020-01-01 00:00:00') TO ('2020-02-01 00:00:00');
CREATE TABLE partition_range_part03 (
id integer,
a int,
b int,
created_date timestamp without time zone
);
ALTER TABLE ONLY partition_range ATTACH PARTITION partition_range_part03 FOR VALUES FROM ('2020-02-01 00:00:00') TO ('2020-03-01 00:00:00');
CREATE TABLE partition_range_part04 (
id integer,
a int,
b int,
created_date timestamp without time zone
);
ALTER TABLE ONLY partition_range ATTACH PARTITION partition_range_part04 FOR VALUES FROM ('2020-03-01 00:00:00') TO ('2020-04-01 00:00:00');
CREATE TABLE partition_range_part05 (
id integer,
a int,
b int,
created_date timestamp without time zone
);
ALTER TABLE ONLY partition_range ATTACH PARTITION partition_range_part05 FOR VALUES FROM ('2020-04-01 00:00:00') TO ('2020-05-01 00:00:00');
When a large number of partitioned tables exist, if the created_date
partition key is not specified in queries, the query performance is reduced.
EXPLAIN (costs off) SELECT * FROM partition_range WHERE ID = 6;
The following result is returned:
QUERY PLAN
------------------------------------------
Append
-> Seq Scan on partition_range_part01
Filter: (id = 6)
-> Seq Scan on partition_range_part02
Filter: (id = 6)
-> Seq Scan on partition_range_part03
Filter: (id = 6)
(7 rows)
To resolve this issue, you can create global indexes to improve query performance. Execute the following statement to create a global index:
CREATE UNIQUE INDEX idx_partition_range_global ON partition_range(id) global;
After the global index is created, the query performance is improved, as shown in the following example:
EXPLAIN (costs off) SELECT * FROM partition_range WHERE ID = 6;
The following result is returned:
QUERY PLAN
-----------------------------------------------------------------------
Global Index Scan using idx_partition_range_global on partition_range
Index Cond: (id = 6)
(2 rows)
You can attach partitions to or detach partitions from partitioned tables for which global indexes are created.
Attach a new partition.
CREATE TABLE partition_range_part06 ( id integer, a int, b int, created_date timestamp without time zone ); ALTER TABLE ONLY partition_range ATTACH PARTITION partition_range_part06 FOR VALUES FROM ('2020-05-01 00:00:00') TO ('2020-06-01 00:00:00');
Detach a previous partition.
ALTER TABLE partition_range DETACH PARTITION partition_range_part01;