1. 程式人生 > >PostgreSQL 11 新特性之分割槽索引

PostgreSQL 11 新特性之分割槽索引

文章目錄

在 PostgreSQL 10 中,分割槽上的索引需要基於各個分割槽手動建立,而不能基於分割槽的父表建立索引。PostgreSQL 11 可以基於分割槽表建立索引。分割槽表上的索引並不會建立一個物理上的索引,而是為每個分割槽上的索引建立一個模板。

分割槽自動索引

如果在分割槽表上建立了一個索引,PostgreSQL 自動為每個分割槽建立具有相同屬性的索引。

CREATE TABLE measurement (
    city_id         int not
null, logdate date not null, peaktemp int, unitsales int ) PARTITION BY RANGE (logdate); CREATE TABLE measurement_y2018 PARTITION OF measurement FOR VALUES FROM ('2018-01-01') TO ('2019-01-01'); CREATE TABLE measurement_y2019 PARTITION OF measurement FOR VALUES FROM
('2019-01-01') TO ('2020-01-01'); CREATE INDEX idx_measurement_peaktemp ON measurement(peaktemp); \d measurement Table "public.measurement" Column | Type | Collation | Nullable | Default -----------+---------+-----------+----------+--------- city_id | integer | | not null
| logdate | date | | not null | peaktemp | integer | | | unitsales | integer | | | Partition key: RANGE (logdate) Indexes: "idx_measurement_peaktemp" btree (peaktemp) Number of partitions: 2 (Use \d+ to list them.)

measurement 表上建立了一個索引 idx_measurement_peaktemp,因此該表上的分割槽也會自動建立相應的索引。

\d measurement_y2018
           Table "public.measurement_y2018"
  Column   |  Type   | Collation | Nullable | Default 
-----------+---------+-----------+----------+---------
 city_id   | integer |           | not null | 
 logdate   | date    |           | not null | 
 peaktemp  | integer |           |          | 
 unitsales | integer |           |          | 
Partition of: measurement FOR VALUES FROM ('2018-01-01') TO ('2019-01-01')
Indexes:
    "measurement_y2018_peaktemp_idx" btree (peaktemp)

自動建立的索引,名稱按照 “{partition name}_{column name}_idx” 的模式定義。多個欄位的複合索引使用下劃線(_)連線欄位名稱。如果索引名稱已經存在,在名稱的最後新增一個數字。如果名稱過長,使用縮寫。

隨後新增的分割槽或者通過 ATTACH PARTITION 掛載的分割槽都會自動建立相應的索引。

CREATE TABLE measurement_y2020 (LIKE measurement);
ALTER TABLE measurement ATTACH PARTITION measurement_y2020
  FOR VALUES FROM ('2020-01-01') TO ('2021-01-01');

\d measurement_y2020
           Table "public.measurement_y2020"
  Column   |  Type   | Collation | Nullable | Default 
-----------+---------+-----------+----------+---------
 city_id   | integer |           | not null | 
 logdate   | date    |           | not null | 
 peaktemp  | integer |           |          | 
 unitsales | integer |           |          | 
Partition of: measurement FOR VALUES FROM ('2020-01-01') TO ('2021-01-01')
Indexes:
    "measurement_y2020_peaktemp_idx" btree (peaktemp)

自動建立的索引不能單獨刪除,可以通過分割槽表統一刪除。

DROP INDEX measurement_y2020_peaktemp_idx;
ERROR:  cannot drop index measurement_y2020_peaktemp_idx because index idx_measurement_peaktemp requires it
HINT:  You can drop index idx_measurement_peaktemp instead.

DROP INDEX idx_measurement_peaktemp;

分割槽表唯一約束

對於 PostgreSQL 10,只能基於分割槽建立唯一約束(PRIMARY KEY 和 UNIQUE KEY),而不能針對分割槽的父表建立唯一約束。PostgreSQL 11 支援分割槽表上的唯一約束。

CREATE TABLE rtable(c1 INT, c2 VARCHAR(10)) PARTITION BY RANGE(c1);
ALTER TABLE rtable ADD CONSTRAINT pk_rtable PRIMARY KEY(c1);
\d rtable
                      Table "public.rtable"
 Column |         Type          | Collation | Nullable | Default 
--------+-----------------------+-----------+----------+---------
 c1     | integer               |           | not null | 
 c2     | character varying(10) |           |          | 
Partition key: RANGE (c1)
Indexes:
    "pk_rtable" PRIMARY KEY, btree (c1)
Number of partitions: 0

新增分割槽或者載入(ATTACH)分割槽時自動建立相應的主鍵:

CREATE TABLE rtable100 PARTITION OF rtable FOR VALUES FROM (1) TO (100);
\d rtable100
                    Table "public.rtable100"
 Column |         Type          | Collation | Nullable | Default 
--------+-----------------------+-----------+----------+---------
 c1     | integer               |           | not null | 
 c2     | character varying(10) |           |          | 
Partition of: rtable FOR VALUES FROM (1) TO (100)
Indexes:
    "rtable100_pkey" PRIMARY KEY, btree (c1)

如果在分割槽表上建立了唯一約束,無法再建立基於外部表(FOREIGN TABLE)的分割槽。因為無法為外部表建立唯一約束。

CREATE FOREIGN TABLE rtable200 PARTITION OF rtable FOR VALUES FROM (101) TO (200) SERVER remote1;
ERROR:  cannot create index on foreign table "rtable200"

主鍵約束或唯一約束必須包含分割槽欄位。這樣才能確保整個分割槽表內的唯一性,因為每個分割槽上的唯一約束只維護自身的唯一性。

CREATE TABLE rtable1(c1 INT, c2 VARCHAR(10)) PARTITION BY RANGE(c1);
ALTER TABLE rtable1 ADD CONSTRAINT pk_table1 PRIMARY KEY(c2);
ERROR:  insufficient columns in PRIMARY KEY constraint definition
DETAIL:  PRIMARY KEY constraint on table "rtable1" lacks column "c1" which is part of the partition key.

新的索引修改語句 ALTER INDEX ATTACH PARTITION 可以將分割槽上的已有索引掛載到分割槽表上的索引。

人生本來短暫,你又何必匆匆!點個贊再走吧!