溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

PostgreSQL中怎么利用表繼承實(shí)現(xiàn)分區(qū)表

發(fā)布時(shí)間:2021-08-07 16:41:48 來源:億速云 閱讀:156 作者:Leah 欄目:關(guān)系型數(shù)據(jù)庫

這篇文章將為大家詳細(xì)講解有關(guān)PostgreSQL中怎么利用表繼承實(shí)現(xiàn)分區(qū)表,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對相關(guān)知識有一定的了解。

概述

分區(qū)指的是將邏輯上一的一個(gè)大表分成多個(gè)小的物理上的片(子表),分區(qū)可以提供以下好處:
.在某些情況下查詢性能能夠顯著提升,特別是當(dāng)那些訪問壓力大的行在一個(gè)分區(qū)或者少數(shù)幾個(gè)分區(qū)時(shí)。分區(qū)可以取代索引的主導(dǎo)列、減小索引尺寸以及使索引中訪問壓力大的部分更有可能被放在內(nèi)存中。

.當(dāng)查詢或更新訪問一個(gè)分區(qū)的大部分行時(shí),可以通過該分區(qū)上的一個(gè)順序掃描來取代分散到整個(gè)表上的索引和隨機(jī)訪問,這樣可以改善性能。

.如果需求計(jì)劃使用劃分設(shè)計(jì),可以通過增加或移除分區(qū)來完成批量載入和刪除。ALTER TABLE NO INHERIT和DROP TABLE都遠(yuǎn)快于一個(gè)批量操作。這些命令也完全避免了由批量DELETE造成的VACUUM負(fù)載。

.很少使用的數(shù)據(jù)可以被遷移到便宜且較慢的存儲介質(zhì)上。

當(dāng)一個(gè)表非常大時(shí),分區(qū)所帶來的好處是非常值得的。一個(gè)表何種情況下會從分區(qū)中獲益取決于應(yīng)用,一個(gè)經(jīng)驗(yàn)法則是當(dāng)表的尺寸超過了數(shù)據(jù)庫服務(wù)器物理內(nèi)存時(shí),分區(qū)會為表帶來好處。

當(dāng)前,PostgreSQL支持通過表繼承來實(shí)現(xiàn)分區(qū)。每個(gè)分區(qū)必須被創(chuàng)建為單個(gè)父表的子表。父表它本身正常來說是空的;它存在僅僅是代表整個(gè)數(shù)據(jù)庫。在試圖設(shè)置分區(qū)之前應(yīng)該要先熟悉表繼承。

在PostgreSQL中可以實(shí)現(xiàn)下列形式的分區(qū):

范圍分區(qū)
表被根據(jù)一個(gè)關(guān)鍵列或一組列劃分為"范圍"分區(qū),不同的分區(qū)的范圍之間沒有重疊。例如,我們可以根據(jù)日期范圍劃分分區(qū),或者根據(jù)特定業(yè)務(wù)對象的標(biāo)識符劃分分區(qū)。

列表分區(qū)
通過顯式地列出每一個(gè)分區(qū)中出現(xiàn)的鍵值來劃分表。

實(shí)現(xiàn)分區(qū)
要建立一個(gè)分區(qū)表,可以這樣做:
1.創(chuàng)建一個(gè)"主"表,所有的分區(qū)都將繼承它。
這個(gè)表將不包含數(shù)據(jù)。不要對這個(gè)表定義任何檢查約束,除非你打算將這些約束應(yīng)用到所有的分區(qū)。同樣也不需要定義任何索引或者唯一約束。

2.創(chuàng)建一些繼承于主表的"子"表。通常,這些表不會在從主表繼承的列集中增加任何列。
們將這些子表認(rèn)為是分區(qū),盡管它們在各方面來看普通的PostgreSQL表(或者可能是外部表)。

3.為分區(qū)表增加表約束以定義每個(gè)分區(qū)中允許的鍵值。
典型的例子是:

CHECK ( x = 1 )
CHECK ( county IN ( 'Oxfordshire', 'Buckinghamshire', 'Warwickshire' ))
CHECK ( outletID >= 100 AND outletID < 200 )

要確保這些約束能夠保證在不同分區(qū)所允許的鍵值之間不存在重疊。設(shè)置范圍約束時(shí)一種常見的錯誤是:

CHECK ( outletID BETWEEN 100 AND 200 )
CHECK ( outletID BETWEEN 200 AND 300 )

這是錯誤的,因?yàn)殒I值200并沒有被清楚地分配到某一個(gè)分區(qū)。注意在語法上范圍劃分和列表劃分沒有區(qū)別,這些術(shù)語只是為了描述方便而存在。

4.對于每一個(gè)分區(qū),在關(guān)鍵列上創(chuàng)建一個(gè)索引,并創(chuàng)建其他我們所需要的索引(關(guān)鍵索引并不是嚴(yán)格必要的,但是在大部分情況下它都是有用的。如果我們希望鍵值是唯一的,則我們還要為每一個(gè)分區(qū)創(chuàng)建一個(gè)唯一或者主鍵約束。)

5.還可以有選擇地定義一個(gè)觸發(fā)器或者規(guī)則將插入到主表上的數(shù)據(jù)重定向到合適的分區(qū)上。

6.確保在postgresql.conf中constraint_exclusion配置參數(shù)沒有被禁用。如果它被禁用,查詢將不會被按照期望的方式優(yōu)化。

例如,假設(shè)我們正在為一個(gè)大型的冰淇淋公司構(gòu)建一個(gè)數(shù)據(jù)庫。該公司測量每天在每一個(gè)區(qū)域的最高氣溫以及冰淇淋銷售。在概念上,我們想要一個(gè)這樣的表:

CREATE TABLE measurement (
city_id int not null,
logdate date not null,
peaktemp int,
unitsales int
);
insert into measurement values(1,date '2008-02-01',1,1);

由于該表的主要用途是為管理層提供在線報(bào)告,我們知道大部分查詢將只會訪問上周、上月或者上季度的數(shù)據(jù)。為了減少需要保存的舊數(shù)據(jù)的量,我們決定只保留最近3年的數(shù)據(jù)。在每一個(gè)月的開始,我們將刪除最老的一個(gè)月的數(shù)據(jù)。

在這種情況下,我們可以使用分區(qū)來幫助我們滿足對于測量表的所有不同需求。按照上面所勾勒的步驟,分區(qū)可以這樣來建立:

1.主表是measurement表,完全按照以上的方式聲明。

jydb=# CREATE TABLE measurement (
jydb(#     city_id         int not null,
jydb(#     logdate         date not null,
jydb(#     peaktemp        int,
jydb(#     unitsales       int
jydb(# );
CREATE TABLE

2.下一步我們?yōu)槊恳粋€(gè)活動月創(chuàng)建一個(gè)分區(qū):

CREATE TABLE measurement_y2006m02 ( ) INHERITS (measurement);
CREATE TABLE measurement_y2006m03 ( ) INHERITS (measurement);
...
CREATE TABLE measurement_y2007m11 ( ) INHERITS (measurement);
CREATE TABLE measurement_y2007m12 ( ) INHERITS (measurement);
CREATE TABLE measurement_y2008m01 ( ) INHERITS (measurement);

每一個(gè)分區(qū)自身都是完整的表,但是它們的定義都是從measurement表繼承而來。

這解決了我們的一個(gè)問題:刪除舊數(shù)據(jù)。每個(gè)月,我們所需要做的是在最舊的子表上執(zhí)行一個(gè)DROP TABLE命令并為新一個(gè)月的數(shù)據(jù)創(chuàng)建一個(gè)新的子表。

3.我們必須提供不重疊的表約束。和前面簡單地創(chuàng)建分區(qū)表不同,實(shí)際的表創(chuàng)建腳本應(yīng)該是:

jydb=# CREATE TABLE measurement_y2006m02 (
jydb(#     CHECK ( logdate >= DATE '2006-02-01' AND logdate < DATE '2006-03-01' ) jydb(# ) INHERITS (measurement); CREATE TABLE jydb=# CREATE TABLE measurement_y2006m03 ( jydb(# CHECK ( logdate >= DATE '2006-03-01' AND logdate < DATE '2006-04-01' ) jydb(# ) INHERITS (measurement); CREATE TABLE jydb=# CREATE TABLE measurement_y2008m02 ( jydb(# CHECK ( logdate >= DATE '2008-02-01' AND logdate < DATE '2008-03-01' )
jydb(# ) INHERITS (measurement);
CREATE TABLE
jydb=# CREATE TABLE measurement_y2008m03
jydb-#   (LIKE measurement INCLUDING DEFAULTS INCLUDING CONSTRAINTS);
CREATE TABLE

4.我們可能在關(guān)鍵列上也需要索引:

CREATE INDEX measurement_y2006m02_logdate ON measurement_y2006m02 (logdate);
CREATE INDEX measurement_y2006m03_logdate ON measurement_y2006m03 (logdate);
...
CREATE INDEX measurement_y2007m11_logdate ON measurement_y2007m11 (logdate);
CREATE INDEX measurement_y2007m12_logdate ON measurement_y2007m12 (logdate);
CREATE INDEX measurement_y2008m01_logdate ON measurement_y2008m01 (logdate);

在這里我們選擇不增加更多的索引。

5.我們希望我們的應(yīng)用能夠使用INSERT INTO measurement ...并且數(shù)據(jù)將被重定向到合適的分區(qū)表。我們可以通過為主表附加一個(gè)合適的觸發(fā)器函數(shù)來實(shí)現(xiàn)這一點(diǎn)。如果數(shù)據(jù)將只被增加到最后一個(gè)分區(qū),我們可以使用一個(gè)非常簡單的觸發(fā)器函數(shù):

CREATE OR REPLACE FUNCTION measurement_insert_trigger()
RETURNS TRIGGER AS $$
BEGIN
    INSERT INTO measurement_y2008m01 VALUES (NEW.*);
    RETURN NULL;
END;
$$
LANGUAGE plpgsql;

完成函數(shù)創(chuàng)建后,我們創(chuàng)建一個(gè)調(diào)用該觸發(fā)器函數(shù)的觸發(fā)器:

CREATE TRIGGER insert_measurement_trigger
    BEFORE INSERT ON measurement
    FOR EACH ROW EXECUTE PROCEDURE measurement_insert_trigger();

我們必須在每個(gè)月重新定義觸發(fā)器函數(shù),這樣它才會總是指向當(dāng)前分區(qū)。而觸發(fā)器的定義則不需要被更新。

我們也可能希望插入數(shù)據(jù)時(shí)服務(wù)器會自動地定位應(yīng)該加入數(shù)據(jù)的分區(qū)。我們可以通過一個(gè)更復(fù)雜的觸發(fā)器函數(shù)來實(shí)現(xiàn)之,例如:

jydb=# CREATE OR REPLACE FUNCTION measurement_insert_trigger()
jydb-# RETURNS TRIGGER AS $$
jydb$# BEGIN
jydb$#
jydb$#     IF ( NEW.logdate >= DATE '2006-03-01' AND
jydb$#             NEW.logdate < DATE '2006-04-01' ) THEN jydb$# INSERT INTO measurement_y2006m03 VALUES (NEW.*); jydb$# ELSIF ( NEW.logdate >= DATE '2008-02-01' AND
jydb$#             NEW.logdate < DATE '2008-03-01' ) THEN
jydb$#         INSERT INTO measurement_y2008m02 VALUES (NEW.*);
jydb$#     ELSE
jydb$#         RAISE EXCEPTION 'Date out of range.  Fix the measurement_insert_trigger() function!';
jydb$#     END IF;
jydb$#     RETURN NULL;
jydb$# END;
jydb$# $$
jydb-# LANGUAGE plpgsql;
CREATE FUNCTION
jydb=# CREATE TRIGGER insert_measurement_trigger
jydb-#     BEFORE INSERT ON measurement
jydb-#     FOR EACH ROW EXECUTE PROCEDURE measurement_insert_trigger();
CREATE TRIGGER
jydb=# insert into measurement values(1,date '2006-03-03',1,1);
INSERT 0 0
jydb=# insert into measurement values(1,date '2008-02-03',1,1);
INSERT 0 0
jydb=# select * from measurement_y2006m03;
 city_id |  logdate   | peaktemp | unitsales
---------+------------+----------+-----------
       1 | 2006-03-02 |        1 |         1
       1 | 2006-03-03 |        1 |         1
(2 rows)
jydb=# select * from measurement_y2008m02;
 city_id |  logdate   | peaktemp | unitsales
---------+------------+----------+-----------
       1 | 2008-02-01 |        1 |         1
       1 | 2008-02-01 |        1 |         1
       1 | 2008-02-01 |        1 |         1
       1 | 2008-02-02 |        1 |         1
       1 | 2008-02-03 |        1 |         1
(5 rows)
jydb=# select * from measurement;
 city_id |  logdate   | peaktemp | unitsales
---------+------------+----------+-----------
       1 | 2006-03-02 |        1 |         1
       1 | 2006-03-03 |        1 |         1
       1 | 2008-02-01 |        1 |         1
       1 | 2008-02-01 |        1 |         1
       1 | 2008-02-01 |        1 |         1
       1 | 2008-02-02 |        1 |         1
       1 | 2008-02-03 |        1 |         1
(7 rows)

觸發(fā)器的定義和以前一樣。注意每一個(gè)IF測試必須準(zhǔn)確地匹配它的分區(qū)的CHECK約束。當(dāng)該函數(shù)比單月形式更加復(fù)雜時(shí),并不需要頻繁地更新它,因?yàn)榭梢栽谛枰臅r(shí)候提前加入分支。

注意: 在實(shí)踐中,如果大部分插入都會進(jìn)入最新的分區(qū),最好先檢查它。為了簡潔,我們?yōu)橛|發(fā)器的檢查采用了和本例中其他部分一致的順序。

如我們所見,一個(gè)復(fù)雜的分區(qū)模式可能需要大量的DDL。在上面的例子中,我們需要每月創(chuàng)建一個(gè)新分區(qū),所以最好能夠編寫一個(gè)腳本自動地生成所需的DDL。

管理分區(qū)
通常當(dāng)初始定義的表傾向于動態(tài)變化時(shí),一組分區(qū)會被創(chuàng)建。刪除舊的分區(qū)并周期性地為新數(shù)據(jù)增加新分區(qū)是很常見的。劃分的一個(gè)最重要的優(yōu)點(diǎn)是可以通過操縱分區(qū)結(jié)構(gòu)來使得這種痛苦的任務(wù)幾乎是自發(fā)地完成,而不需要去物理地移除大量的數(shù)據(jù)。

移除舊數(shù)據(jù)的最簡單的選項(xiàng)是直接刪除不再需要的分區(qū):

jydb=# DROP TABLE measurement_y2006m02;
DROP TABLE

這可以非??斓貏h除百萬級別的記錄,因?yàn)樗恍枰鹨坏貏h除記錄。

另一個(gè)經(jīng)常使用的選項(xiàng)是將分區(qū)從被劃分的表中移除,但是把它作為一個(gè)獨(dú)立的表保留下來:

ALTER TABLE measurement_y2006m02 NO INHERIT measurement;

這允許在數(shù)據(jù)被刪除前執(zhí)行更進(jìn)一步的操作。例如,這是一個(gè)很有用的時(shí)機(jī)通過COPY、pg_dump或類似的工具來備份數(shù)據(jù)。這也是進(jìn)行數(shù)據(jù)聚集、執(zhí)行其他數(shù)據(jù)操作或運(yùn)行報(bào)表的好時(shí)機(jī)。

相似地我們也可以增加新分區(qū)來處理新數(shù)據(jù)。我們可以在被劃分的表中創(chuàng)建一個(gè)新的空分區(qū):

jydb=# CREATE TABLE measurement_y2008m02 (
jydb(#     CHECK ( logdate >= DATE '2008-02-01' AND logdate < DATE '2008-03-01' )
jydb(# ) INHERITS (measurement);
CREATE TABLE

作為一種選擇方案,有時(shí)創(chuàng)建一個(gè)在分區(qū)結(jié)構(gòu)之外的新表更方便,并且在以后才將它作為一個(gè)合適的分區(qū)。這使得數(shù)據(jù)可以在出現(xiàn)于分區(qū)表中之前被載入、檢查和轉(zhuǎn)換:

jydb=# CREATE TABLE measurement_y2008m03
jydb-#   (LIKE measurement INCLUDING DEFAULTS INCLUDING CONSTRAINTS);
CREATE TABLE
jydb=# ALTER TABLE measurement_y2008m03 ADD CONSTRAINT y2008m03
jydb-#    CHECK ( logdate >= DATE '2008-03-01' AND logdate < DATE '2008-04-01' );
ALTER TABLE
jydb=# ALTER TABLE measurement_y2008m03 INHERIT measurement;
ALTER TABLE

分區(qū)與約束排除
約束排除是一種查詢優(yōu)化技術(shù),它可以為按照以上方式定義的分區(qū)表提高性能。例如:

jydb=# SET constraint_exclusion = on;
SET
jydb=# SELECT count(*) FROM measurement WHERE logdate >= DATE '2008-01-01';
 count
-------
     3
(1 row)

如果沒有約束排除,上述查詢將掃描measurement表的每一個(gè)分區(qū)。在啟用約束排除后,規(guī)劃器將檢查每一個(gè)分區(qū)的約束來確定該分區(qū)需不需要被掃描,因?yàn)榉謪^(qū)中可能不包含滿足查詢WHERE子句的行。如果規(guī)劃器能夠證實(shí)這一點(diǎn),則它將會把該分區(qū)排除在查詢計(jì)劃之外。

可以使用EXPLAIN命令來顯示開啟了constraint_exclusion的計(jì)劃和沒有開啟該選項(xiàng)的計(jì)劃之間的區(qū)別。一個(gè)典型的未優(yōu)化的計(jì)劃是:

jydb=# SET constraint_exclusion = off;
SET
jydb=# EXPLAIN SELECT count(*) FROM measurement WHERE logdate >= DATE '2008-01-01';
                                    QUERY PLAN
-----------------------------------------------------------------------------------
 Aggregate  (cost=107.47..107.48 rows=1 width=8)
   ->  Append  (cost=0.00..102.69 rows=1913 width=0)
         ->  Seq Scan on measurement  (cost=0.00..3.31 rows=62 width=0)
               Filter: (logdate >= '2008-01-01'::date)
         ->  Seq Scan on measurement_y2006m03  (cost=0.00..33.12 rows=617 width=0)
               Filter: (logdate >= '2008-01-01'::date)
         ->  Seq Scan on measurement_y2008m02  (cost=0.00..33.12 rows=617 width=0)
               Filter: (logdate >= '2008-01-01'::date)
         ->  Seq Scan on measurement_y2008m03  (cost=0.00..33.12 rows=617 width=0)
               Filter: (logdate >= '2008-01-01'::date)
(10 rows)

其中的某些或者全部分區(qū)將會使用索引掃描而不是全表順序掃描,但是關(guān)鍵在于根本不需要掃描舊分區(qū)來回答這個(gè)查詢。當(dāng)我們開啟約束排除后,對于同一個(gè)查詢我們會得到一個(gè)更加廉價(jià)的計(jì)劃:

jydb=# SET constraint_exclusion = on;
SET
jydb=# EXPLAIN SELECT count(*) FROM measurement WHERE logdate >= DATE '2008-01-01';
                                    QUERY PLAN
-----------------------------------------------------------------------------------
 Aggregate  (cost=72.80..72.81 rows=1 width=8)
   ->  Append  (cost=0.00..69.56 rows=1296 width=0)
         ->  Seq Scan on measurement  (cost=0.00..3.31 rows=62 width=0)
               Filter: (logdate >= '2008-01-01'::date)
         ->  Seq Scan on measurement_y2008m02  (cost=0.00..33.12 rows=617 width=0)
               Filter: (logdate >= '2008-01-01'::date)
         ->  Seq Scan on measurement_y2008m03  (cost=0.00..33.12 rows=617 width=0)
               Filter: (logdate >= '2008-01-01'::date)
(8 rows)

注意約束排除只由CHECK約束驅(qū)動,而非索引的存在。因此,沒有必要在關(guān)鍵列上定義索引。是否在給定分區(qū)上定義索引取決于我們希望查詢經(jīng)常掃描表的大部分還是小部分。在后一種情況中索引將會發(fā)揮作用。

constraint_exclusion的默認(rèn)(也是推薦)設(shè)置實(shí)際上既不是on也不是off,而是一個(gè)被稱為partition的中間設(shè)置,這使得該技術(shù)只被應(yīng)用于將要在分區(qū)表上工作的查詢。設(shè)置on將使得規(guī)劃器在所有的查詢中檢查CHECK約束,即使簡單查詢不會從中受益。

替代的分區(qū)方法
另一種將插入數(shù)據(jù)重定向到合適的分區(qū)的方法是在主表上建立規(guī)則而不是觸發(fā)器,例如:

jydb=# CREATE RULE measurement_insert_y2006m03 AS
jydb-# ON INSERT TO measurement WHERE
jydb-# ( logdate >= DATE '2006-03-01' AND logdate < DATE '2006-04-01' ) jydb-# DO INSTEAD jydb-# INSERT INTO measurement_y2006m03 VALUES (NEW.*); CREATE RULE jydb=# CREATE RULE measurement_insert_y2008m02 AS jydb-# ON INSERT TO measurement WHERE jydb-# ( logdate >= DATE '2008-02-01' AND logdate < DATE '2008-03-01' )
jydb-# DO INSTEAD
jydb-# INSERT INTO measurement_y2008m02 VALUES (NEW.*);
CREATE RULE
jydb=# insert into measurement values(1,date '2006-03-02',1,1);
INSERT 0 0
jydb=# insert into measurement values(1,date '2008-02-02',1,1);
INSERT 0 0
jydb=# select * from measurement;
 city_id |  logdate   | peaktemp | unitsales
---------+------------+----------+-----------
       1 | 2006-03-02 |        1 |         1
       1 | 2008-02-01 |        1 |         1
       1 | 2008-02-01 |        1 |         1
       1 | 2008-02-01 |        1 |         1
       1 | 2008-02-02 |        1 |         1
(5 rows)
jydb=# select * from measurement_y2006m03;
 city_id |  logdate   | peaktemp | unitsales
---------+------------+----------+-----------
       1 | 2006-03-02 |        1 |         1
(1 row)
jydb=# select * from measurement_y2008m02;
 city_id |  logdate   | peaktemp | unitsales
---------+------------+----------+-----------
       1 | 2008-02-01 |        1 |         1
       1 | 2008-02-01 |        1 |         1
       1 | 2008-02-01 |        1 |         1
       1 | 2008-02-02 |        1 |         1
(4 rows)

一個(gè)規(guī)則比一個(gè)觸發(fā)器具有明顯更高的負(fù)荷,但是該負(fù)荷是由每個(gè)查詢承擔(dān)而不是每一個(gè)行,因此這種方法可能對于批量插入的情況有益。但是,在大部分情況下觸發(fā)器方法能提供更好的性能。

注意COPY會忽略規(guī)則。如果希望使用COPY來插入數(shù)據(jù),我們將希望將數(shù)據(jù)復(fù)制到正確的分區(qū)表而不是主表。COPY會引發(fā)觸發(fā)器,因此如果使用觸發(fā)器方法就可以正常地使用它。

規(guī)則方法的另一個(gè)缺點(diǎn)是如果一組規(guī)則沒有覆蓋被插入的數(shù)據(jù),則該數(shù)據(jù)將被插入到主表中而不會發(fā)出任何錯誤。

分區(qū)也可以使用一個(gè)UNION ALL視圖來組織。例如:

CREATE VIEW measurement AS
          SELECT * FROM measurement_y2006m02
UNION ALL SELECT * FROM measurement_y2006m03
...
UNION ALL SELECT * FROM measurement_y2007m11
UNION ALL SELECT * FROM measurement_y2007m12
UNION ALL SELECT * FROM measurement_y2008m01;

但是,如果要增加或者刪除單獨(dú)的分區(qū),就需要重新地創(chuàng)建視圖。在實(shí)踐中,相對于使用繼承,這種方法很少被推薦。

警告
下面的警告適用于分區(qū)表:
.沒有自動的方法來驗(yàn)證所有的CHECK約束是互斥的。創(chuàng)建代碼來生成分區(qū)并創(chuàng)建或修改相關(guān)對象比手工寫命令要更安全。

.這里展示的模式都假設(shè)分區(qū)的關(guān)鍵列從不改變,或者是其改變不足以導(dǎo)致它被移到另一個(gè)分區(qū)。一個(gè)嘗試將行移到另一個(gè)分區(qū)的UPDATE會失敗,因?yàn)镃HECK約束的存在。如果我們需要處理這類情況,我們可以在分區(qū)表上放置合適的更新觸發(fā)器,但是它會使得結(jié)構(gòu)的管理更加復(fù)雜。

.如果我們在使用手工的VACUUM或ANALYZE命令,別忘了需要在每一個(gè)分區(qū)上都運(yùn)行一次。以下的命令:
ANALYZE measurement;
只會處理主表。

.帶有ON CONFLICT子句的INSERT 語句不太可能按照預(yù)期的方式工作,因?yàn)镺N CONFLICT動作 只有在指定的目標(biāo)關(guān)系(而非它的子關(guān)系)上有唯一違背的情況下才會被采用。

下面的警告適用于約束排除:
.只有在查詢的WHERE子句包含常量(或者外部提供的參數(shù))時(shí),約束排除才會起效。例如,一個(gè)與非不變函數(shù)(例如CURRENT_TIMESTAMP)的比較不能被優(yōu)化,因?yàn)橐?guī)劃器不知道該函數(shù)的值在運(yùn)行時(shí)會落到哪個(gè)分區(qū)內(nèi)。

.保持分區(qū)約束簡單,否則規(guī)劃器可能沒有辦法驗(yàn)證無需訪問的分區(qū)。按前面的例子所示,為列表分區(qū)使用簡單相等條件或者為范圍分區(qū)使用簡單范圍測試。一個(gè)好的經(jīng)驗(yàn)法則是分區(qū)約束應(yīng)該只包含使用B-tree索引操作符的比較,比較的雙方應(yīng)該是分區(qū)列和常量。

.在約束排除期間,主表所有的分區(qū)上的所有約束都會被檢查,所以大量的分區(qū)將會顯著地增加查詢規(guī)劃時(shí)間。使用這些技術(shù)的分區(qū)在大約最多100個(gè)分區(qū)的情況下工作得很好,但是不要嘗試使用成千個(gè)分區(qū)。

關(guān)于PostgreSQL中怎么利用表繼承實(shí)現(xiàn)分區(qū)表就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI