Bu konu, pg_pathman uzantısının yaygın kullanım örneklerini açıklar.
Genel bilgiler
PolarDB for PostgreSQL bölümlenmiş tabloların performansını artırmak için pg_pathman uzantısını içerir. Bu uzantı bir bölüm yönetimi ve optimizasyon mekanizması sunar.
pg_pathman uzantısını oluşturun
pg_pathman uzantısının bölüm yönetimi özelliklerini kullanmak için bizimle iletişime geçin.
CREATE EXTENSION IF NOT EXISTS pg_pathman;
Uzantıyı oluşturduktan sonra sürümünü görüntülemek için aşağıdaki SQL ifadesini çalıştırabilirsiniz:
SELECT extname,extversion FROM pg_extension WHERE extname = 'pg_pathman';
Aşağıdaki sonuç döner:
extname | extversion
------------+------------
pg_pathman | 1.5
(1 row)
Uzantıyı güncelleyin
PolarDB for PostgreSQL geliştirilmiş veritabanı hizmetleri sunmak amacıyla eklentilerini düzenli olarak günceller. Bir eklentiyi güncellemek için önce kümeyi en son sürüme yükseltmeniz gerekir.
Uzantı özellikleri
Hash bölümleme ve aralık bölümlemeyi destekler.
Bölümleri oluşturmak ve ana tablodan veri taşımak için işlevleri kullanan otomatik bölüm yönetimini destekler. Ayrıca, mevcut tabloları işlevlerle iliştirmenize veya ayırmanıza olanak tanıyan manuel bölüm yönetimini de destekler.
int, float ve date gibi özel alanlar dahil olmak üzere bölüm anahtarı sütunları için yaygın veri türlerini destekler.
JOIN'ler ve alt sorgular dahil olmak üzere bölümlenmiş tablolar için verimli sorgu planları oluşturur.
Dinamik bölüm seçimini uygulamak üzere özel plan düğümlerini, yani
RuntimeAppendveRuntimeMergeAppendkullanır.PartitionFilterekleme tetikleyicilerine verimli bir alternatif sunar.Yeni bölümlerin otomatik olarak oluşturulmasını destekler. Bu özellik şu anda yalnızca aralıkla bölümlenmiş tablolar için kullanılabilir.
Verimliliği artırmak amacıyla
copy from/tokullanarak bölümlenmiş tablolar üzerinde doğrudan okuma ve yazma işlemlerini destekler.Bir tetikleyici aracılığıyla bölüm anahtarı sütunlarının güncellenmesini destekler. Olası bir performans etkisini önlemek için bölüm anahtarı sütunlarını güncellemeye ihtiyacınız yoksa bu tetikleyiciyi eklemeyin.
Bir bölüm oluşturulduğunda otomatik olarak tetiklenen özel geri arama işlevlerini tanımlamanıza olanak tanır.
İşlemleri engellemeden arka planda bölümlenmiş tablolar oluşturur ve ana tablodaki verileri bölümlere taşır.
Foreign Data Wrappers (FDW) desteği sunar. postgres_fdw veya başka bir FDW'yi desteklemek için
pg_pathman.insert_into_fdw=(disabled | postgres | any_fdw)parametresini yapılandırabilirsiniz.
Kullanım
Daha fazla bilgi için GitHub üzerindeki projeye bakın.
İlgili görünümler ve tablolar
pg_pathman bölümlenmiş tabloları sürdürmek için işlevler kullanır ve bu tabloların durumunu kontrol etmeniz için birkaç görünüm sağlar. Görünümler şunlardır:
-
pathman_config
CREATE TABLE IF NOT EXISTS pathman_config ( partrel REGCLASS NOT NULL PRIMARY KEY, -- OID of the primary table attname TEXT NOT NULL, -- Name of the partition key column parttype INTEGER NOT NULL, -- Partitioning type (hash or range) range_interval TEXT, -- Interval for range partitions CHECK (parttype IN (1, 2)) /* check for allowed part types */ ); -
pathman_config_params
CREATE TABLE IF NOT EXISTS pathman_config_params ( partrel REGCLASS NOT NULL PRIMARY KEY, -- OID of the primary table enable_parent BOOLEAN NOT NULL DEFAULT TRUE, -- Specifies whether to filter the primary table in the optimizer auto BOOLEAN NOT NULL DEFAULT TRUE, -- Specifies whether to automatically create a new partition if it does not exist during an insert operation init_callback REGPROCEDURE NOT NULL DEFAULT 0); -- OID of the callback function for partition creation -
pathman_concurrent_part_tasks
-- helper SRF function CREATE OR REPLACE FUNCTION show_concurrent_part_tasks() RETURNS TABLE ( userid REGROLE, pid INT, dbid OID, relid REGCLASS, processed INT, status TEXT) AS 'pg_pathman', 'show_concurrent_part_tasks_internal' LANGUAGE C STRICT; CREATE OR REPLACE VIEW pathman_concurrent_part_tasks AS SELECT * FROM show_concurrent_part_tasks(); -
pathman_partition_list
-- helper SRF function CREATE OR REPLACE FUNCTION show_partition_list() RETURNS TABLE ( parent REGCLASS, partition REGCLASS, parttype INT4, partattr TEXT, range_min TEXT, range_max TEXT) AS 'pg_pathman', 'show_partition_list_internal' LANGUAGE C STRICT; CREATE OR REPLACE VIEW pathman_partition_list AS SELECT * FROM show_partition_list();
Bölüm yönetimi
Aralık bölümleme
Aralık bölümleri oluşturmak için dört yönetim işlevi bulunur. Bunlardan ikisi başlangıç değeri, aralık ve bölüm sayısı belirtmenize olanak tanır. Tanımları şöyledir:
create_range_partitions(relation REGCLASS, -- OID of the primary table
attribute TEXT, -- Name of the partition key column
start_value ANYELEMENT, -- Start value
p_interval ANYELEMENT, -- Interval. Can be of any data type suitable for any type of partitioned table.
p_count INTEGER DEFAULT NULL, -- Number of partitions to create
partition_data BOOLEAN DEFAULT TRUE) -- Specifies whether to immediately migrate data from the primary table to partitions. This is not recommended. Use the non-blocking migration function partition_table_concurrently() instead.
create_range_partitions(relation REGCLASS, -- OID of the primary table
attribute TEXT, -- Name of the partition key column
start_value ANYELEMENT, -- Start value
p_interval INTERVAL, -- Interval. The interval data type is used for time-based partitioned tables.
p_count INTEGER DEFAULT NULL, -- Number of partitions to create
partition_data BOOLEAN DEFAULT TRUE) -- Specifies whether to immediately migrate data from the primary table to partitions. This is not recommended. Use the non-blocking migration function partition_table_concurrently() instead.
Diğer iki işlev ise başlangıç değeri, bitiş değeri ve aralık belirtmenize olanak tanır. Tanımları şöyledir:
create_partitions_from_range(relation REGCLASS, -- OID of the primary table
attribute TEXT, -- Name of the partition key column
start_value ANYELEMENT, -- Start value
end_value ANYELEMENT, -- End value
p_interval ANYELEMENT, -- Interval. Can be of any data type suitable for any type of partitioned table.
partition_data BOOLEAN DEFAULT TRUE) -- Specifies whether to immediately migrate data from the primary table to partitions. This is not recommended. Use the non-blocking migration function partition_table_concurrently() instead.
create_partitions_from_range(relation REGCLASS, -- OID of the primary table
attribute TEXT, -- Name of the partition key column
start_value ANYELEMENT, -- Start value
end_value ANYELEMENT, -- End value
p_interval INTERVAL, -- Interval. The interval data type is used for time-based partitioned tables.
partition_data BOOLEAN DEFAULT TRUE) -- Specifies whether to immediately migrate data from the primary table to partitions. This is not recommended. Use the non-blocking migration function partition_table_concurrently() instead.
Örneğin:
-
Bölümlenecek ana tabloyu oluşturun ve test verilerini ekleyin.
--- Create the primary table to be partitioned CREATE TABLE part_test(id int, info text, crt_time timestamp not null); -- The partition key column must have a NOT NULL constraint --- Insert test data to simulate a primary table that already contains data INSERT INTO part_test SELECT id,md5(random()::text),clock_timestamp() + (id||' hour')::interval from generate_series(1,10000) t(id);Ana tablodaki verileri sorgulayın:
SELECT * FROM part_test limit 10;Aşağıdaki sonuç döner:
id | info | crt_time ----+----------------------------------+---------------------------- 1 | 36fe1adedaa5b848caec4941f87d443a | 2016-10-25 10:27:13.206713 2 | c7d7358e196a9180efb4d0a10269c889 | 2016-10-25 11:27:13.206893 3 | 005bdb063550579333264b895df5b75e | 2016-10-25 12:27:13.206904 4 | 6c900a0fc50c6e4da1ae95447c89dd55 | 2016-10-25 13:27:13.20691 5 | 857214d8999348ed3cb0469b520dc8e5 | 2016-10-25 14:27:13.206916 6 | 4495875013e96e625afbf2698124ef5b | 2016-10-25 15:27:13.206921 7 | 82488cf7e44f87d9b879c70a9ed407d4 | 2016-10-25 16:27:13.20693 8 | a0b92547c8f17f79814dfbb12b8694a0 | 2016-10-25 17:27:13.206936 9 | 2ca09e0b85042b476fc235e75326b41b | 2016-10-25 18:27:13.206942 10 | 7eb762e1ef7dca65faf413f236dff93d | 2016-10-25 19:27:13.206947 (10 rows) -
Bölümleri oluşturun. Her bölüm bir aylık veri aralığını içerir.
--- Create partitions. Each partition contains data for a one-month span. SELECT create_range_partitions('part_test'::regclass, -- OID of the primary table 'crt_time', -- Name of the partition key column '2016-10-25 00:00:00'::timestamp, -- Start value interval '1 month', -- Interval. The interval data type is used for time-based partitioned tables. 24, -- Number of partitions to create false) ; -- Do not migrate data -
Engelsiz taşıma işlevini kullanarak verileri ana tablodan taşıyın.
--- Before data migration, the data is still in the primary table SELECT count(*) FROM ONLY part_test; count ------- 10000 (1 row) --- Non-blocking migration function partition_table_concurrently(relation REGCLASS, -- OID of the primary table batch_size INTEGER DEFAULT 1000, -- Number of records to migrate in a single transaction batch sleep_time FLOAT8 DEFAULT 1.0) -- The duration to sleep before retrying if acquiring row locks fails. The task exits after 60 retries. --- Use the non-blocking migration function to migrate data from the primary table SELECT partition_table_concurrently('part_test'::regclass, 10000, 1.0); --- After migration, the primary table is empty. All data has been moved to the partitions. SELECT count(*) FROM ONLY part_test; count ------- 0 (1 row) -
Veri taşıma tamamlandıktan sonra ana tabloyu devre dışı bırakarak yürütme planlarında görünmesini engelleyin.
--- Disable the primary table SELECT set_enable_parent('part_test'::regclass, false); --- Verification EXPLAIN SELECT * FROM part_test WHERE crt_time = '2016-10-25 00:00:00'::timestamp; QUERY PLAN --------------------------------------------------------------------------------- Append (cost=0.00..16.18 rows=1 width=45) -> Seq Scan on part_test_1 (cost=0.00..16.18 rows=1 width=45) Filter: (crt_time = '2016-10-25 00:00:00'::timestamp without time zone) (3 rows)
Aralıkla bölümlenmiş tabloları kullanırken şu en iyi uygulamaları izleyin:
Bölüm anahtarı sütunu NOT NULL kısıtlamasına sahip olmalıdır.
Mevcut tüm kayıtları kapsayacak sayıda bölüm bulunmalıdır.
Engelsiz taşıma işlevini kullanın.
Veri taşıma tamamlandıktan sonra ana tabloyu devre dışı bırakın.
Hash bölümleme
Başlangıç değeri, aralık ve bölüm sayısını belirterek hash bölümleri oluşturmanıza olanak tanıyan bir yönetim işlevi aşağıdaki gibidir:
create_hash_partitions(relation REGCLASS, -- OID of the primary table
attribute TEXT, -- Name of the partition key column
partitions_count INTEGER, -- Number of partitions to create
partition_data BOOLEAN DEFAULT TRUE) -- Specifies whether to immediately migrate data from the primary table to partitions. This is not recommended. Use the non-blocking migration function partition_table_concurrently() instead.
Örneğin:
-
Bölümlenecek ana tabloyu oluşturun ve test verilerini ekleyin.
--- Create the primary table to be partitioned CREATE TABLE part_test(id int, info text, crt_time timestamp not null); -- The partition key column must have a NOT NULL constraint --- Insert test data to simulate a primary table that already contains data INSERT INTO part_test SELECT id,md5(random()::text),clock_timestamp() + (id||' hour')::interval FROM generate_series(1,10000) t(id);Ana tablodaki verileri sorgulayın:
SELECT * FROM part_test limit 10;Aşağıdaki sonuç döner:
id | info | crt_time ----+----------------------------------+---------------------------- 1 | 29ce4edc70dbfbe78912beb7c4cc95c2 | 2016-10-25 10:47:32.873879 2 | e0990a6fb5826409667c9eb150fef386 | 2016-10-25 11:47:32.874048 3 | d25f577a01013925c203910e34470695 | 2016-10-25 12:47:32.874059 4 | 501419c3f7c218e562b324a1bebfe0ad | 2016-10-25 13:47:32.874065 5 | 5e5e22bdf110d66a5224a657955ba158 | 2016-10-25 14:47:32.87407 6 | 55d2d4fd5229a6595e0dd56e13d32be4 | 2016-10-25 15:47:32.874076 7 | 1dfb9a783af55b123c7a888afe1eb950 | 2016-10-25 16:47:32.874081 8 | 41eeb0bf395a4ab1e08691125ae74bff | 2016-10-25 17:47:32.874087 9 | 83783d69cc4f9bb41a3978fe9e13d7fa | 2016-10-25 18:47:32.874092 10 | affc9406d5b3412ae31f7d7283cda0dd | 2016-10-25 19:47:32.874097 (10 rows) -
Bölümleri oluşturun.
--- Create 128 partitions SELECT create_hash_partitions('part_test'::regclass, -- OID of the primary table 'crt_time', -- Name of the partition key column 128, -- Number of partitions to create false) ; -- Do not migrate data -
Engelsiz taşıma işlevini kullanarak verileri ana tablodan taşıyın.
--- Before data migration, the data is still in the primary table SELECT count(*) FROM ONLY part_test; count ------- 10000 (1 row) --- Non-blocking migration function partition_table_concurrently(relation REGCLASS, -- OID of the primary table batch_size INTEGER DEFAULT 1000, -- Number of records to migrate in a single transaction batch sleep_time FLOAT8 DEFAULT 1.0) -- The duration to sleep before retrying if acquiring row locks fails. The task exits after 60 retries. --- Use the non-blocking migration function to migrate data from the primary table SELECT partition_table_concurrently('part_test'::regclass, 10000, 1.0); --- After migration, the primary table is empty. All data has been moved to the partitions. SELECT count(*) FROM ONLY part_test; count ------- 0 (1 row) -
Veri taşıma tamamlandıktan sonra ana tabloyu devre dışı bırakarak yürütme planlarında görünmesini engelleyin.
--- Disable the primary table SELECT set_enable_parent('part_test'::regclass, false);Yürütme planını doğrulayın:
--- Query a single partition EXPLAIN SELECT * FROM part_test WHERE crt_time = '2016-10-25 00:00:00'::timestamp; QUERY PLAN --------------------------------------------------------------------------------- Append (cost=0.00..1.91 rows=1 width=45) -> Seq Scan on part_test_122 (cost=0.00..1.91 rows=1 width=45) Filter: (crt_time = '2016-10-25 00:00:00'::timestamp without time zone) (3 rows)Bölümlenmiş tablodaki aşağıdaki kısıtlama, pg_pathman'ın dönüşümü otomatik olarak gerçekleştirdiğini gösterir. Buna karşılık, geleneksel kalıtım
SELECT * FROM part_test WHERE crt_time = '2016-10-25 00:00:00'::timestamp;gibi bir ifade için bölüm budamayı gerçekleştiremez.\d+ part_test_122 Table "public.part_test_122" Column | Type | Modifiers | Storage | Stats target | Description ----------+-----------------------------+-----------+----------+--------------+------------- id | integer | | plain | | info | text | | extended | | crt_time | timestamp without time zone | not null | plain | | Check constraints: "pathman_part_test_122_3_check" CHECK (get_hash_part_idx(timestamp_hash(crt_time), 128) = 122) Inherits: part_test
Hash ile bölümlenmiş tabloları kullanırken şu en iyi uygulamaları izleyin:
Bölüm anahtarı sütunu NOT NULL kısıtlamasına sahip olmalıdır.
Engelsiz taşıma işlevini kullanın.
Veri taşıma tamamlandıktan sonra ana tabloyu devre dışı bırakın.
pg_pathman ifade biçimiyle sınırlı değildir. Bu nedenle
select * from part_test where crt_time = '2016-10-25 00:00:00'::timestamp;gibi bir ifade de hash bölümleme için kullanılabilir.Hash bölümleme için bölüm anahtarı sütunu int veri türüyle sınırlı değildir. Otomatik dönüşüm için bir hash işlevi kullanılır.
Verileri bölümlere taşıyın
Bölümlenmiş tabloyu oluştururken ana tablodan veri taşımadıysanız verileri taşımak için engelsiz taşıma işlevini kullanabilirsiniz.
WITH tmp AS (DELETE FROM primary_table limit xx nowait returning *) INSERT INTO partition SELECT * FROM tmp;
Alternatif olarak, satırları işaretlemek ve ardından DELETE ve INSERT işlemlerini gerçekleştirmek için aşağıdaki ifadeyi kullanabilirsiniz.
SELECT array_agg(ctid) FROM primary_table limit xx FOR UPDATE nowait;
İşlevin tanımı şöyledir:
partition_table_concurrently(relation REGCLASS, -- OID of the primary table
batch_size INTEGER DEFAULT 1000, -- Number of records to migrate in a single transaction batch
sleep_time FLOAT8 DEFAULT 1.0) -- The duration to sleep before retrying if acquiring row locks fails. The task exits after 60 retries.
Örneğin:
SELECT partition_table_concurrently('part_test'::regclass,
10000,
1.0);
Arka plandaki veri taşıma görevini görüntüleyebilirsiniz.
SELECT * FROM pathman_concurrent_part_tasks;
Aralık bölümünü ayırın
Bir bölüm çok büyük hale gelirse bunu iki bölüme ayırabilirsiniz. Bu özellik şu anda yalnızca aralıkla bölümlenmiş tablolar için kullanılabilir. Aşağıdaki işlevi kullanabilirsiniz:
split_range_partition(partition REGCLASS, -- OID of the partition
split_value ANYELEMENT, -- Split value
partition_name TEXT DEFAULT NULL) -- Name of the new partition table created after the split
Örneğin:
-
Aralık bölümleme örneğinden bölümlenmiş tabloyu kullanın. Tablo şeması aşağıdaki gibidir.
\d+ part_test Table "public.part_test" Column | Type | Modifiers | Storage | Stats target | Description ----------+-----------------------------+-----------+----------+--------------+------------- id | integer | | plain | | info | text | | extended | | crt_time | timestamp without time zone | not null | plain | | Child tables: part_test_1, part_test_10, part_test_11, part_test_12, part_test_13, part_test_14, part_test_15, part_test_16, part_test_17, part_test_18, part_test_19, part_test_2, part_test_20, part_test_21, part_test_22, part_test_23, part_test_24, part_test_3, part_test_4, part_test_5, part_test_6, part_test_7, part_test_8, part_test_9 \d+ part_test_1 Table "public.part_test_1" Column | Type | Modifiers | Storage | Stats target | Description ----------+-----------------------------+-----------+----------+--------------+------------- id | integer | | plain | | info | text | | extended | | crt_time | timestamp without time zone | not null | plain | | Check constraints: "pathman_part_test_1_3_check" CHECK (crt_time >= '2016-10-25 00:00:00'::timestamp without time zone AND crt_time < '2016-11-25 00:00:00'::timestamp without time zone) Inherits: part_test -
Bölümü ayırın.
SELECT split_range_partition('part_test_1'::regclass, -- OID of the partition '2016-11-10 00:00:00'::timestamp, -- Split value 'part_test_1_2'); -- Name of the partition tableAyırma işleminden sonraki iki tablo aşağıdaki gibidir:
\d+ part_test_1 Table "public.part_test_1" Column | Type | Modifiers | Storage | Stats target | Description ----------+-----------------------------+-----------+----------+--------------+------------- id | integer | | plain | | info | text | | extended | | crt_time | timestamp without time zone | not null | plain | | Check constraints: "pathman_part_test_1_3_check" CHECK (crt_time >= '2016-10-25 00:00:00'::timestamp without time zone AND crt_time < '2016-11-10 00:00:00'::timestamp without time zone) Inherits: part_test \d+ part_test_1_2 Table "public.part_test_1_2" Column | Type | Modifiers | Storage | Stats target | Description ----------+-----------------------------+-----------+----------+--------------+------------- id | integer | | plain | | info | text | | extended | | crt_time | timestamp without time zone | not null | plain | | Check constraints: "pathman_part_test_1_2_3_check" CHECK (crt_time >= '2016-11-10 00:00:00'::timestamp without time zone AND crt_time < '2016-11-25 00:00:00'::timestamp without time zone) Inherits: part_testVeriler otomatik olarak yeni bölümlere taşınır.
SELECT count(*) FROM part_test_1; count ------- 373 (1 row) SELECT count(*) FROM part_test_1_2; count ------- 360 (1 row)Kalıtım ilişkisi aşağıdaki gibidir:
\d+ part_test Table "public.part_test" Column | Type | Modifiers | Storage | Stats target | Description ----------+-----------------------------+-----------+----------+--------------+------------- id | integer | | plain | | info | text | | extended | | crt_time | timestamp without time zone | not null | plain | | Child tables: part_test_1, part_test_10, part_test_11, part_test_12, part_test_13, part_test_14, part_test_15, part_test_16, part_test_17, part_test_18, part_test_19, part_test_1_2, -- New table part_test_2, part_test_20, part_test_21, part_test_22, part_test_23, part_test_24, part_test_3, part_test_4, part_test_5, part_test_6, part_test_7, part_test_8, part_test_9
Aralık bölümlerini birleştirin
Bu özellik şu anda yalnızca aralık bölümleme için kullanılabilir ve bölümlerin bitişik olması gerekir. Aşağıdaki işlevi çağırabilirsiniz:
--- Specify the two partitions to merge
merge_range_partitions(partition1 REGCLASS, partition2 REGCLASS)
Bir örnek şöyledir:
-
Birleştirme işlemini gerçekleştirmek için Aralık bölümünü ayırma örneğinden tabloları kullanın.
SELECT merge_range_partitions('part_test_1'::regclass, 'part_test_1_2'::regclass);NotBitişik olmayan bölümleri birleştirmeye çalışırsanız bir hata döner.
SELECT merge_range_partitions('part_test_2'::regclass, 'part_test_12'::regclass) ; ERROR: merge failed, partitions must be adjacent CONTEXT: PL/pgSQL function merge_range_partitions_internal(regclass,regclass,regclass,anyelement) line 27 at RAISE SQL statement "SELECT public.merge_range_partitions_internal($1, $2, $3, NULL::timestamp without time zone)" PL/pgSQL function merge_range_partitions(regclass,regclass) line 44 at EXECUTE -
Birleştirmeden sonra özgün bölümlerden biri silinir.
\d part_test_1_2 Did not find any relation named "part_test_1_2". \d part_test_1 Table "public.part_test_1" Column | Type | Modifiers ----------+-----------------------------+----------- id | integer | info | text | crt_time | timestamp without time zone | not null Check constraints: "pathman_part_test_1_3_check" CHECK (crt_time >= '2016-10-25 00:00:00'::timestamp without time zone AND crt_time < '2016-11-25 00:00:00'::timestamp without time zone) Inherits: part_test SELECT count(*) FROM part_test_1; count ------- 733 (1 row)
Aralık bölümü ekleyin
Ana tablo zaten bölümlenmişse yeni bölümleri birkaç şekilde ekleyebilirsiniz. Bu bölümde üç yöntem açıklanmaktadır: aralık bölümü ekleme, aralık bölümü önekleme ve belirli bir başlangıç değerine sahip aralık bölümü ekleme.
Aralık bölümü ekleyin (sona)
Aralık bölümü eklediğinizde (bölümü sona eklediğinizde) bölümlenmiş tablonun ilk oluşturulması sırasında belirtilen aralık kullanılır. Aşağıda gösterildiği gibi her bölümlenmiş tablo için ilk aralığı bulmak üzere pathman_config görünümünü sorgulayabilirsiniz:
SELECT * FROM pathman_config;
partrel | attname | parttype | range_interval
-----------+----------+----------+----------------
part_test | crt_time | 2 | 1 mon
(1 row)
Bölüm ekleme işlevi aşağıdaki gibidir. Bir tablo alanı belirtme şu anda desteklenmemektedir.
append_range_partition(parent REGCLASS, -- OID of the primary table
partition_name TEXT DEFAULT NULL, -- Name of the new partition table. This is optional.
tablespace TEXT DEFAULT NULL) -- Tablespace for the new partition table. This is optional.
Bir örnek şöyledir:
SELECT append_range_partition('part_test'::regclass);
\d+ part_test_25
Table "public.part_test_25"
Column | Type | Modifiers | Storage | Stats target | Description
----------+-----------------------------+-----------+----------+--------------+-------------
id | integer | | plain | |
info | text | | extended | |
crt_time | timestamp without time zone | not null | plain | |
Check constraints:
"pathman_part_test_25_3_check" CHECK (crt_time >= '2018-10-25 00:00:00'::timestamp without time zone AND crt_time < '2018-11-25 00:00:00'::timestamp without time zone)
Inherits: part_test
\d+ part_test_24
Table "public.part_test_24"
Column | Type | Modifiers | Storage | Stats target | Description
----------+-----------------------------+-----------+----------+--------------+-------------
id | integer | | plain | |
info | text | | extended | |
crt_time | timestamp without time zone | not null | plain | |
Check constraints:
"pathman_part_test_24_3_check" CHECK (crt_time >= '2018-09-25 00:00:00'::timestamp without time zone AND crt_time < '2018-10-25 00:00:00'::timestamp without time zone)
Inherits: part_test
Aralık bölümü önekleyin (başa)
Aralık bölümünü öne eklemek için aşağıdaki işlevi kullanın:
prepend_range_partition(parent REGCLASS,
partition_name TEXT DEFAULT NULL,
tablespace TEXT DEFAULT NULL)
Örneğin:
SELECT prepend_range_partition('part_test'::regclass);
\d+ part_test_26
Table "public.part_test_26"
Column | Type | Modifiers | Storage | Stats target | Description
----------+-----------------------------+-----------+----------+--------------+-------------
id | integer | | plain | |
info | text | | extended | |
crt_time | timestamp without time zone | not null | plain | |
Check constraints:
"pathman_part_test_26_3_check" CHECK (crt_time >= '2016-09-25 00:00:00'::timestamp without time zone AND crt_time < '2016-10-25 00:00:00'::timestamp without time zone)
Inherits: part_test
\d+ part_test_1
Table "public.part_test_1"
Column | Type | Modifiers | Storage | Stats target | Description
----------+-----------------------------+-----------+----------+--------------+-------------
id | integer | | plain | |
info | text | | extended | |
crt_time | timestamp without time zone | not null | plain | |
Check constraints:
"pathman_part_test_1_3_check" CHECK (crt_time >= '2016-10-25 00:00:00'::timestamp without time zone AND crt_time < '2016-11-25 00:00:00'::timestamp without time zone)
Inherits: part_test
Belirli bir başlangıç değeriyle bölüm ekleyin
Başlangıç ve bitiş değerlerini belirterek bir aralık bölümü ekleyebilirsiniz. Bölüm, mevcut bölümlerle çakışmadığı sürece oluşturulabilir. Bu yöntem bitişik bölümler oluşturmanızı gerektirmez. Örneğin, mevcut bölümler 2010'dan 2015'e kadar olan aralığı kapsıyorsa 2015'ten 2020'ye kadar olan aralığı kapsamadan doğrudan 2020 yılı için bir bölüm oluşturabilirsiniz. İşlev aşağıdaki gibidir:
add_range_partition(relation REGCLASS, -- OID of the primary table
start_value ANYELEMENT, -- Start value
end_value ANYELEMENT, -- End value
partition_name TEXT DEFAULT NULL, -- Name of the partition
tablespace TEXT DEFAULT NULL) -- Tablespace where the partition is created
Örneğin:
SELECT add_range_partition('part_test'::regclass, -- OID of the primary table
'2020-01-01 00:00:00'::timestamp, -- Start value
'2020-02-01 00:00:00'::timestamp); -- End value
\d+ part_test_27
Table "public.part_test_27"
Column | Type | Modifiers | Storage | Stats target | Description
----------+-----------------------------+-----------+----------+--------------+-------------
id | integer | | plain | |
info | text | | extended | |
crt_time | timestamp without time zone | not null | plain | |
Check constraints:
"pathman_part_test_27_3_check" CHECK (crt_time >= '2020-01-01 00:00:00'::timestamp without time zone AND crt_time < '2020-02-01 00:00:00'::timestamp without time zone)
Inherits: part_test
Bölümü silin
-
Tek bir aralık bölümünü silmek için aşağıdaki işlevi kullanın:
drop_range_partition(partition TEXT, -- Name of the partition delete_data BOOLEAN DEFAULT TRUE) -- Specifies whether to delete the partition data. If false, the data is migrated to the primary table. Drop RANGE partition and all of its data if delete_data is true. -
Tüm bölümleri silmek ve verilerin ana tabloya taşınıp taşınmayacağını belirtmek için aşağıdaki işlevi kullanın:
drop_partitions(parent REGCLASS, delete_data BOOLEAN DEFAULT FALSE) Drop partitions of the parent table (both foreign and local relations). If delete_data is false, the data is copied to the parent table first. Default is false.
Örneğin:
-
Bir bölümü silin ve verilerini ana tabloya taşıyın.
SELECT drop_range_partition('part_test_1',false); SELECT drop_range_partition('part_test_2',false);Ana tablonun mevcut veri hacmini sorgulayın:
SELECT count(*) FROM part_test; count ------- 10000 (1 row) -
Bir bölümü ve verilerini silin. Veriler ana tabloya taşınmaz.
SELECT drop_range_partition('part_test_3',true);Ana tablonun mevcut veri hacmini sorgulayın:
SELECT count(*) FROM part_test; count ------- 9256 (1 row) SELECT count(*) FROM ONLY part_test; count ------- 1453 (1 row) -
Tüm bölümleri silin.
SELECT drop_partitions('part_test'::regclass, false); -- Delete all partition tables and migrate the data to the primary tableAna tablodaki verileri sorgulayın:
SELECT count(*) FROM part_test; count ------- 9256 (1 row)
Bölümü iliştirin
Mevcut bir tabloyu bölümlenmiş ana tabloya iliştirebilirsiniz. Mevcut tablonun, bırakılan sütunlar dahil olmak üzere ana tabloyla aynı şemaya sahip olması gerekir. Tutarlılığı kontrol etmek için pg_attribute görünümünü inceleyebilirsiniz. İşlev aşağıdaki gibidir:
attach_range_partition(relation REGCLASS, -- OID of the primary table
partition REGCLASS, -- OID of the partition table
start_value ANYELEMENT, -- Start value
end_value ANYELEMENT) -- End value
Bir örnek şöyledir:
-
Bölüm olarak kullanılacak bir tablo oluşturun.
CREATE TABLE part_test_1 (like part_test including all); -
Mevcut tabloyu ana tabloya iliştirin.
\d+ part_test Table "public.part_test" Column | Type | Modifiers | Storage | Stats target | Description ----------+-----------------------------+-----------+----------+--------------+------------- id | integer | | plain | | info | text | | extended | | crt_time | timestamp without time zone | not null | plain | | \d+ part_test_1 Table "public.part_test_1" Column | Type | Modifiers | Storage | Stats target | Description ----------+-----------------------------+-----------+----------+--------------+------------- id | integer | | plain | | info | text | | extended | | crt_time | timestamp without time zone | not null | plain | | SELECT attach_range_partition('part_test'::regclass, 'part_test_1'::regclass, '2019-01-01 00:00:00'::timestamp, '2019-02-01 00:00:00'::timestamp);Bir bölümü iliştirdiğinizde kalıtım ilişkisi ve kısıtlamalar otomatik olarak oluşturulur.
\d+ part_test_1 Table "public.part_test_1" Column | Type | Modifiers | Storage | Stats target | Description ----------+-----------------------------+-----------+----------+--------------+------------- id | integer | | plain | | info | text | | extended | | crt_time | timestamp without time zone | not null | plain | | Check constraints: "pathman_part_test_1_3_check" CHECK (crt_time >= '2019-01-01 00:00:00'::timestamp without time zone AND crt_time < '2019-02-01 00:00:00'::timestamp without time zone) Inherits: part_test
Bölümü ayırın
Bir bölümü ana tablonun kalıtım hiyerarşisinden kaldırabilirsiniz. Bu işlem verileri silmez ancak kalıtım ilişkisini ve kısıtlamaları kaldırır. İşlev aşağıdaki gibidir:
detach_range_partition(partition REGCLASS) -- Specify the partition name to convert it into a standard table
Bir örnek şöyledir:
-
Ana tablonun ve bölümün mevcut veri hacmini sorgulayın.
SELECT count(*) FROM part_test; count ------- 9256 (1 row) SELECT count(*) FROM part_test_2; count ------- 733 (1 row) -
Bölümü ayırın.
SELECT detach_range_partition('part_test_2');Ana tablonun ve bölümün mevcut veri hacmini sorgulayın.
SELECT count(*) FROM part_test_2; count ------- 733 (1 row) SELECT count(*) FROM part_test; count ------- 8523 (1 row)
pg_pathman'ı devre dışı bırakın
Tek bir bölümlenmiş ana tablo için pg_pathman'ı devre dışı bırakabilirsiniz. İşlev aşağıdaki gibidir:
disable_pathman_for işlemi geri alınamaz. Dikkatli kullanın.
\sf disable_pathman_for
CREATE OR REPLACE FUNCTION public.disable_pathman_for(parent_relid regclass)
RETURNS void
LANGUAGE plpgsql
STRICT
AS $function$
BEGIN
PERFORM public.validate_relname(parent_relid);
DELETE FROM public.pathman_config WHERE partrel = parent_relid;
PERFORM public.drop_triggers(parent_relid);
/* Notify backend about changes */
PERFORM public.on_remove_partitions(parent_relid);
END
$function$
Aşağıda bir örnek verilmiştir:
SELECT disable_pathman_for('part_test');
\d+ part_test
Table "public.part_test"
Column | Type | Modifiers | Storage | Stats target | Description
----------+-----------------------------+-----------+----------+--------------+-------------
id | integer | | plain | |
info | text | | extended | |
crt_time | timestamp without time zone | not null | plain | |
Child tables: part_test_10,
part_test_11,
part_test_12,
part_test_13,
part_test_14,
part_test_15,
part_test_16,
part_test_17,
part_test_18,
part_test_19,
part_test_20,
part_test_21,
part_test_22,
part_test_23,
part_test_24,
part_test_25,
part_test_26,
part_test_27,
part_test_28,
part_test_29,
part_test_3,
part_test_30,
part_test_31,
part_test_32,
part_test_33,
part_test_34,
part_test_35,
part_test_4,
part_test_5,
part_test_6,
part_test_7,
part_test_8,
part_test_9
\d+ part_test_10
Table "public.part_test_10"
Column | Type | Modifiers | Storage | Stats target | Description
----------+-----------------------------+-----------+----------+--------------+-------------
id | integer | | plain | |
info | text | | extended | |
crt_time | timestamp without time zone | not null | plain | |
Check constraints:
"pathman_part_test_10_3_check" CHECK (crt_time >= '2017-06-25 00:00:00'::timestamp without time zone AND crt_time < '2017-07-25 00:00:00'::timestamp without time zone)
Inherits: part_test
pg_pathman uzantısını devre dışı bıraktıktan sonra kalıtım ilişkileri ve kısıtlamalar değişmeden kalır. Tek fark, pg_pathman uzantısının artık yürütme planında özel bir tarama sağlamamasıdır. Uzantı devre dışı bırakıldıktan sonraki yürütme planı aşağıdaki gibidir:
EXPLAIN SELECT * FROM part_test WHERE crt_time='2017-06-25 00:00:00'::timestamp;
QUERY PLAN
---------------------------------------------------------------------------------
Append (cost=0.00..16.00 rows=2 width=45)
-> Seq Scan on part_test (cost=0.00..0.00 rows=1 width=45)
Filter: (crt_time = '2017-06-25 00:00:00'::timestamp without time zone)
-> Seq Scan on part_test_10 (cost=0.00..16.00 rows=1 width=45)
Filter: (crt_time = '2017-06-25 00:00:00'::timestamp without time zone)
(5 rows)
Gelişmiş bölüm yönetimi
Ana tabloyu devre dışı bırakın
Ana tablodaki tüm veriler bölümlere taşındıktan sonra ana tabloyu devre dışı bırakabilirsiniz. İşlev aşağıdaki gibidir:
set_enable_parent(relation REGCLASS, value BOOLEAN)
Include/exclude parent table into/from query plan.
In original PostgreSQL planner parent table is always included into query plan even if it's empty which can lead to additional overhead.
You can use disable_parent() if you are never going to use parent table as a storage.
Default value depends on the partition_data parameter that was specified during initial partitioning in create_range_partitions() or create_partitions_from_range() functions.
If the partition_data parameter was true then all data have already been migrated to partitions and parent table disabled.
Otherwise it is enabled.
Örneğin:
SELECT set_enable_parent('part_test', false);
Bölümleri otomatik olarak genişletin
Aralıkla bölümlenmiş tablolar için otomatik bölüm oluşturmayı etkinleştirebilirsiniz. Yeni eklenen veriler mevcut bölümlerin aralığına düşmezse yeni bir bölüm otomatik olarak oluşturulur.
set_auto(relation REGCLASS, value BOOLEAN)
Enable/disable auto partition propagation (only for RANGE partitioning).
It is enabled by default.
Örneğin:
-
Test tablosunun mevcut bölümlerini sorgulayın.
\d+ part_test Table "public.part_test" Column | Type | Modifiers | Storage | Stats target | Description ----------+-----------------------------+-----------+----------+--------------+------------- id | integer | | plain | | info | text | | extended | | crt_time | timestamp without time zone | not null | plain | | Child tables: part_test_10, part_test_11, part_test_12, part_test_13, part_test_14, part_test_15, part_test_16, part_test_17, part_test_18, part_test_19, part_test_20, part_test_21, part_test_22, part_test_23, part_test_24, part_test_25, part_test_26, part_test_3, part_test_4, part_test_5, part_test_6, part_test_7, part_test_8, part_test_9 \d+ part_test_26 Table "public.part_test_26" Column | Type | Modifiers | Storage | Stats target | Description ----------+-----------------------------+-----------+----------+--------------+------------- id | integer | | plain | | info | text | | extended | | crt_time | timestamp without time zone | not null | plain | | Check constraints: "pathman_part_test_26_3_check" CHECK (crt_time >= '2018-09-25 00:00:00'::timestamp without time zone AND crt_time < '2018-10-25 00:00:00'::timestamp without time zone) Inherits: part_test \d+ part_test_25 Table "public.part_test_25" Column | Type | Modifiers | Storage | Stats target | Description ----------+-----------------------------+-----------+----------+--------------+------------- id | integer | | plain | | info | text | | extended | | crt_time | timestamp without time zone | not null | plain | | Check constraints: "pathman_part_test_25_3_check" CHECK (crt_time >= '2018-08-25 00:00:00'::timestamp without time zone AND crt_time < '2018-09-25 00:00:00'::timestamp without time zone) Inherits: part_test -
Mevcut bölümlerin aralığının dışındaki bir değeri ekleyin. Bu işlem, ilk kurulum sırasında belirtilen aralığa göre gerekli sayıda bölümü otomatik olarak oluşturur. Bu işlemin uzun sürebileceğini unutmayın.
INSERT INTO part_test VALUES (1,'test','2222-01-01'::timestamp);Mevcut bölüm durumunu sorgulayabilirsiniz:
\d+ part_test Table "public.part_test" Column | Type | Modifiers | Storage | Stats target | Description ----------+-----------------------------+-----------+----------+--------------+------------- id | integer | | plain | | info | text | | extended | | crt_time | timestamp without time zone | not null | plain | | Child tables: part_test_10, part_test_100, part_test_1000, part_test_1001, ......
Aralıkla bölümlenmiş tablolar için otomatik bölüm oluşturmayı etkinleştirmemenizi öneririz. Çok sayıda bölümün otomatik olarak oluşturulması oldukça zaman alıcı olabilir.
Geri arama işlevleri
Geri arama işlevi, her bölüm oluşturulduğunda otomatik olarak tetiklenen bir işlevdir. Örneğin, DDL mantıksal çoğaltma için bir geri arama işlevi kullanarak DDL ifadelerini bir tabloda kaydedebilirsiniz. Geri arama ayarlama işlevi aşağıdaki gibidir:
set_init_callback(relation REGCLASS, callback REGPROC DEFAULT 0)
Set partition creation callback to be invoked for each attached or created partition (both HASH and RANGE).
The callback must have the following signature:
part_init_callback(args JSONB) RETURNS VOID.
Parameter arg consists of several fields whose presence depends on partitioning type:
/* RANGE-partitioned table abc (child abc_4) */
{
"parent": "abc",
"parttype": "2",
"partition": "abc_4",
"range_max": "401",
"range_min": "301"
}
/* HASH-partitioned table abc (child abc_0) */
{
"parent": "abc",
"parttype": "1",
"partition": "abc_0"
}
Örneğin:
-
Bir geri arama işlevi oluşturun.
CREATE OR REPLACE FUNCTION f_callback_test(jsonb) RETURNS void AS $$ DECLARE BEGIN CREATE TABLE if NOT EXISTS rec_part_ddl(id serial primary key, parent name, parttype int, partition name, range_max text, range_min text); if ($1->>'parttype')::int = 1 then raise notice 'parent: %, parttype: %, partition: %', $1->>'parent', $1->>'parttype', $1->>'partition'; INSERT INTO rec_part_ddl(parent, parttype, partition) values (($1->>'parent')::name, ($1->>'parttype')::int, ($1->>'partition')::name); elsif ($1->>'parttype')::int = 2 then raise notice 'parent: %, parttype: %, partition: %, range_max: %, range_min: %', $1->>'parent', $1->>'parttype', $1->>'partition', $1->>'range_max', $1->>'range_min'; INSERT INTO rec_part_ddl(parent, parttype, partition, range_max, range_min) values (($1->>'parent')::name, ($1->>'parttype')::int, ($1->>'partition')::name, $1->>'range_max', $1->>'range_min'); END if; END; $$ LANGUAGE plpgsql strict; -
Bir test tablosu hazırlayın.
CREATE TABLE tt(id int, info text, crt_time timestamp not null); --- Set the callback function for the test table SELECT set_init_callback('tt'::regclass, 'f_callback_test'::regproc); --- Create partitions SELECT create_range_partitions('tt'::regclass, -- OID of the primary table 'crt_time', -- Name of the partition key column '2016-10-25 00:00:00'::timestamp, -- Start value interval '1 month', -- Interval. The interval data type is used for time-based partitioned tables. 24, -- Number of partitions to create false) ; -
Geri arama işlevinin çağrılıp çağrılmadığını kontrol edin.
SELECT * FROM rec_part_ddl;Aşağıdaki sonuç döner:
id | parent | parttype | partition | range_max | range_min ----+--------+----------+-----------+---------------------+--------------------- 1 | tt | 2 | tt_1 | 2016-11-25 00:00:00 | 2016-10-25 00:00:00 2 | tt | 2 | tt_2 | 2016-12-25 00:00:00 | 2016-11-25 00:00:00 3 | tt | 2 | tt_3 | 2017-01-25 00:00:00 | 2016-12-25 00:00:00 4 | tt | 2 | tt_4 | 2017-02-25 00:00:00 | 2017-01-25 00:00:00 5 | tt | 2 | tt_5 | 2017-03-25 00:00:00 | 2017-02-25 00:00:00 6 | tt | 2 | tt_6 | 2017-04-25 00:00:00 | 2017-03-25 00:00:00 7 | tt | 2 | tt_7 | 2017-05-25 00:00:00 | 2017-04-25 00:00:00 8 | tt | 2 | tt_8 | 2017-06-25 00:00:00 | 2017-05-25 00:00:00 9 | tt | 2 | tt_9 | 2017-07-25 00:00:00 | 2017-06-25 00:00:00 10 | tt | 2 | tt_10 | 2017-08-25 00:00:00 | 2017-07-25 00:00:00 11 | tt | 2 | tt_11 | 2017-09-25 00:00:00 | 2017-08-25 00:00:00 12 | tt | 2 | tt_12 | 2017-10-25 00:00:00 | 2017-09-25 00:00:00 13 | tt | 2 | tt_13 | 2017-11-25 00:00:00 | 2017-10-25 00:00:00 14 | tt | 2 | tt_14 | 2017-12-25 00:00:00 | 2017-11-25 00:00:00 15 | tt | 2 | tt_15 | 2018-01-25 00:00:00 | 2017-12-25 00:00:00 16 | tt | 2 | tt_16 | 2018-02-25 00:00:00 | 2018-01-25 00:00:00 17 | tt | 2 | tt_17 | 2018-03-25 00:00:00 | 2018-02-25 00:00:00 18 | tt | 2 | tt_18 | 2018-04-25 00:00:00 | 2018-03-25 00:00:00 19 | tt | 2 | tt_19 | 2018-05-25 00:00:00 | 2018-04-25 00:00:00 20 | tt | 2 | tt_20 | 2018-06-25 00:00:00 | 2018-05-25 00:00:00 21 | tt | 2 | tt_21 | 2018-07-25 00:00:00 | 2018-06-25 00:00:00 22 | tt | 2 | tt_22 | 2018-08-25 00:00:00 | 2018-07-25 00:00:00 23 | tt | 2 | tt_23 | 2018-09-25 00:00:00 | 2018-08-25 00:00:00 24 | tt | 2 | tt_24 | 2018-10-25 00:00:00 | 2018-09-25 00:00:00 (24 rows)