Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitab1f18e

Browse files
committed
Merge branch 'pathman_pgpro9_5' into PGPRO9_5
Function-based declarative partitioning module
2 parents3c4c199 +ede287c commitab1f18e

24 files changed

+5047
-0
lines changed

‎contrib/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ SUBDIRS = \
3333
oid2name\
3434
pageinspect\
3535
passwordcheck\
36+
pg_pathman\
3637
pg_buffercache\
3738
pg_freespacemap\
3839
pg_prewarm\

‎contrib/pg_pathman/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
*.o
2+
*.so
3+
pg_pathman--*.sql

‎contrib/pg_pathman/Makefile

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# contrib/pg_pathman/Makefile
2+
3+
MODULE_big = pg_pathman
4+
OBJS = init.o pg_pathman.o dsm_array.o rangeset.o pl_funcs.o$(WIN32RES)
5+
6+
EXTENSION = pg_pathman
7+
EXTVERSION = 0.1
8+
DATA_built =$(EXTENSION)--$(EXTVERSION).sql
9+
PGFILEDESC = "pg_pathman - partitioning tool"
10+
11+
REGRESS = pg_pathman
12+
EXTRA_CLEAN =$(EXTENSION)--$(EXTVERSION).sql
13+
14+
ifdefUSE_PGXS
15+
PG_CONFIG = pg_config
16+
PGXS :=$(shell$(PG_CONFIG) --pgxs)
17+
include$(PGXS)
18+
else
19+
subdir = contrib/pg_pathman
20+
top_builddir = ../..
21+
include$(top_builddir)/src/Makefile.global
22+
include$(top_srcdir)/contrib/contrib-global.mk
23+
endif
24+
25+
$(EXTENSION)--$(EXTVERSION).sql: sql/init.sql sql/hash.sql sql/range.sql
26+
cat$^>$@
27+
check: EXTRA_REGRESS_OPTS=--temp-config=$(top_srcdir)/$(subdir)/conf.add

‎contrib/pg_pathman/README.md

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
#pg_pathman
2+
3+
The`pg_pathman` module provides optimized partitioning mechanism and functions to manage partitions.
4+
5+
##pg_pathman Concepts
6+
7+
Partitioning refers to splitting one large table into smaller pieces. Each row in such table assigns to a single partition based on partitioning key. Common partitioning strategies are:
8+
9+
* HASH - maps rows to partitions based on hash function values;
10+
* RANGE - maps data to partitions based on ranges that you establish for each partition;
11+
* LIST - maps data to partitions based on explicitly specified values of partitioning key for each partition.
12+
13+
PostgreSQL supports partitioning via table inheritance. Each partition must be created as child table with CHECK CONSTRAINT. For example:
14+
15+
```
16+
CREATE TABLE test (id SERIAL PRIMARY KEY, title TEXT);
17+
CREATE TABLE test_1 (CHECK ( id >= 100 AND id < 200 )) INHERITS (test);
18+
CREATE TABLE test_2 (CHECK ( id >= 200 AND id < 300 )) INHERITS (test);
19+
```
20+
21+
Despite the flexibility of this approach it has weakness. If query uses filtering the optimizer forced to perform an exhaustive search and check constraints for each partition to determine partitions from which it should select data. If the number of partitions is large the overhead may be significant.
22+
23+
The`pg_pathman` module provides functions to manage partitions and partitioning mechanism optimized based on knowledge of the partitions structure. It stores partitioning configuration in the`pathman_config` table, each row of which contains single entry for partitioned table (relation name, partitioning key and type). During initialization the`pg_pathman` module caches information about child partitions in shared memory in form convenient to perform rapid search. When user executes SELECT query pg_pathman analyzes conditions tree looking for conditions like:
24+
25+
```
26+
VARIABLE OP CONST
27+
```
28+
where`VARIABLE` is partitioning key,`OP` is comparison operator (supported operators are =, <, <=, >, >=),`CONST` is scalar value. For example:
29+
30+
```
31+
WHERE id = 150
32+
```
33+
34+
Based on partitioning type and operator the`pg_pathman` searches corresponding partitions and builds the plan.
35+
36+
##Installation
37+
38+
To install pg_pathman run in psql:
39+
```
40+
CREATE SCHEMA pathman;
41+
CREATE EXTENSION pg_pathman SCHEMA pathman;
42+
```
43+
Then modify shared_preload_libraries parameter in postgres.conf as following:
44+
```
45+
shared_preload_libraries = 'pg_pathman'
46+
```
47+
It will require to restart the PostgreSQL instance.
48+
49+
##pg_pathman Functions
50+
51+
###Partitions Creation
52+
```
53+
create_hash_partitions(
54+
relation TEXT,
55+
attribute TEXT,
56+
partitions_count INTEGER)
57+
```
58+
Performs HASH partitioning for`relation` by integer key`attribute`. Creates`partitions_count` partitions and trigger on INSERT. Data doesn't automatically copied from parent table to partitions. Use`partition_data()` function (see below) to migrate data.
59+
60+
```
61+
create_range_partitions(
62+
relation TEXT,
63+
attribute TEXT,
64+
start_value ANYELEMENT,
65+
interval ANYELEMENT,
66+
premake INTEGER)
67+
```
68+
Performs RANGE partitioning for`relation` by partitioning key`attribute`.`start_value` argument specifies initial value,`interval` sets the range of values in a single partition,`premake` is the number of premade partitions (the only one partition will be created if`premake` is 0).
69+
```
70+
create_range_partitions(
71+
relation TEXT,
72+
attribute TEXT,
73+
start_value ANYELEMENT,
74+
interval INTERVAL,
75+
premake INTEGER)
76+
```
77+
Same as above but suitable for`DATE` and`TIMESTAMP` partitioning keys.
78+
79+
###Utilities
80+
```
81+
partition_data(parent text)
82+
```
83+
Copies data from parent table to its partitions.
84+
```
85+
create_hash_update_trigger(parent TEXT)
86+
```
87+
Creates the trigger on UPDATE for HASH partitions. The UPDATE trigger isn't created by default because of overhead. It is useful in cases when key attribute could be changed.
88+
```
89+
create_hash_update_trigger(parent TEXT)
90+
```
91+
Same as above for RANGE sections.
92+
93+
###Partitions management
94+
```
95+
split_range_partition(partition TEXT, value ANYELEMENT)
96+
```
97+
Splits RANGE`partition` in two by`value`.
98+
```
99+
merge_range_partitions(partition1 TEXT, partition2 TEXT)
100+
```
101+
Merge two adjacent RANGE partitions. Data from`partition2` is copied to`partition1`. Then the`partition2` is removed.
102+
```
103+
append_partition(p_relation TEXT)
104+
```
105+
Appends new partition with the range equal to the range of the previous partition.
106+
```
107+
prepend_partition(p_relation TEXT)
108+
```
109+
Prepends new partition with the range equal to the range of the first partition.
110+
```
111+
disable_partitioning(relation TEXT)
112+
```
113+
Disables`pg_pathman` partitioning mechanism for the specified parent table and removes an insert trigger. Partitions itself remain unchanged.
114+
115+
##Examples
116+
###HASH
117+
Consider an example of HASH partitioning. First create a table with some integer column:
118+
```
119+
CREATE TABLE hash_rel (
120+
id SERIAL PRIMARY KEY,
121+
value INTEGER);
122+
INSERT INTO hash_rel (value) SELECT g FROM generate_series(1, 10000) as g;
123+
```
124+
Then run create_hash_partitions() function with appropriate arguments:
125+
```
126+
SELECT create_hash_partitions('hash_rel', 'value', 100);
127+
```
128+
This will create new partitions but data will still be in the parent table. To move data to the corresponding partitions use partition_data() function:
129+
```
130+
SELECT partition_data('hash_rel');
131+
```
132+
###RANGE
133+
Consider an example of RANGE partitioning. Create a table with numerical or date or timestamp column:
134+
```
135+
CREATE TABLE range_rel (
136+
id SERIAL PRIMARY KEY,
137+
dt TIMESTAMP);
138+
INSERT INTO range_rel (dt) SELECT g FROM generate_series('2010-01-01'::date, '2015-12-31'::date, '1 day') as g;
139+
```
140+
Run create_range_partitions() function to create partitions so that each partition would contain data for one month:
141+
```
142+
SELECT create_range_partitions('range_rel', 'dt', '2010-01-01'::date, '1 month'::interval, 59);
143+
```
144+
It will create 60 partitions (one partition is created regardless of`premake` parameter). Now move data from the parent to partitions.
145+
```
146+
SELECT partition_data('range_rel');
147+
```
148+
To merge to adjacent partitions run merge_range_partitions() function:
149+
```
150+
SELECT merge_range_partitions('range_rel_1', 'range_rel_2');
151+
```
152+
To split partition use split_range_partition() function:
153+
```
154+
SELECT split_range_partition('range_rel_1', '2010-02-15'::date);
155+
```
156+
Now let's create new partition. You can use append_partition() or prepend_partition() functions:
157+
```
158+
SELECT append_partition('range_rel');
159+
SELECT append_partition('range_rel');
160+
```
161+
162+
##Author
163+
Ildar Musin <i.musin@postgrespro.ru> Postgres Professional Ltd., Russia
164+
This module is sponsored by Postgres Professional Ltd., Russia

‎contrib/pg_pathman/README.rus.md

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
#pg_pathman
2+
3+
Модуль`pg_pathman` предоставляет оптимизированный механизм секционирования, а также функции для создания и управления секциями.
4+
5+
##Концепция pg_pathman
6+
7+
Секционирование -- это способ разбиения одной большой таблицы на множество меньших по размеру. Для каждой записи можно однозначно определить секцию, в которой она должна храниться посредством вычисления ключа. Традиционно выделяют три стратегии секционирования:
8+
9+
* HASH - данные равномерно распределяются по секциям в соответствии со значениями hash-функции, вычисленными по некоторому атрибуту;
10+
* RANGE - данные распределяются по секциям, каждая из которых ответственна за заданный диапазон значений аттрибута;
11+
* LIST - для каждой секции определяется набор конкретных значений атрибута.
12+
13+
Секционирование в postgres основано на механизме наследования. Каждому наследнику задается условие CHECK CONSTRAINT. Например:
14+
15+
```
16+
CREATE TABLE test (id SERIAL PRIMARY KEY, title TEXT);
17+
CREATE TABLE test_1 (CHECK ( id >= 100 AND id < 200 )) INHERITS (test);
18+
CREATE TABLE test_2 (CHECK ( id >= 200 AND id < 300 )) INHERITS (test);
19+
```
20+
21+
Несмотря на гибкость, этот механизм обладает недостатками. Так при фильтрации данных оптимизатор вынужден перебирать все дочерние секции и сравнивать условие запроса с CHECK CONSTRAINT-ами секции, чтобы определить из каких секций ему следует загружать данные. При большом количестве секций это создает дополнительные накладные расходы, которые могут свести на нет выигрыш в производительности от применения секционирования.
22+
23+
Модуль`pg_pathman` предоставляет функции для создания и управления
24+
секциями (см. следующий раздел) и механизм секционирования,
25+
оптимизированный с учетом знания о структуре дочерних таблиц. Конфигурация сохраняется таблице`pathman_config`, каждая строка которой содержит запись для одной секционированной таблицы (название таблицы, атрибут и тип разбиения). В процессе инициализации модуля в разделяемую память сохраняется конфигурация дочерних таблиц в удобном для поиска формате. Получив запрос типа`SELECT` к секционированной таблице,`pg_pathman` анализирует дерево условий запроса и выделяет из него условия вида:
26+
27+
```
28+
ПЕРЕМЕННАЯ ОПЕРАТОР КОНСТАНТА
29+
```
30+
где`ПЕРЕМЕННАЯ` -- это атрибут, по которому было выполнено разбиение,`ОПЕРАТОР` -- оператор сравнения (поддерживаются =, <, <=, >, >=),`КОНСТАНТА` -- скалярное значение. Например:
31+
32+
```
33+
WHERE id = 150
34+
```
35+
Затем основываясь на стратегии секционирования и условиях запроса`pg_pathman` выбирает соответствующие секции и строит план.
36+
37+
##Installation
38+
39+
Для установки pg_pathman выполните в командной строке:
40+
```
41+
CREATE SCHEMA pathman;
42+
CREATE EXTENSION pg_pathman SCHEMA pathman;
43+
44+
```
45+
Затем модифицируйте параметр shared_preload_libraries в конфигурационном файле postgres.conf:
46+
```
47+
shared_preload_libraries = 'pg_pathman'
48+
```
49+
Для вступления изменений в силу потребуется перезагрузка сервера PostgreSQL.
50+
51+
##Функции pg_pathman
52+
53+
###Создание секций
54+
```
55+
create_hash_partitions(
56+
relation TEXT,
57+
attribute TEXT,
58+
partitions_count INTEGER)
59+
```
60+
Выполняет HASH-секционирование таблицы`relation` по целочисленному полю`attribute`. Создает`partitions_count` дочерних секций, а также триггер на вставку. Данные из родительской таблицы не копируются автоматически в дочерние. Миграцию данных можно выполнить с помощью функции`partition_data()` (см. ниже), либо вручную.
61+
62+
```
63+
create_range_partitions(
64+
relation TEXT,
65+
attribute TEXT,
66+
start_value ANYELEMENT,
67+
interval ANYELEMENT,
68+
premake INTEGER)
69+
```
70+
Выполняет RANGE-секционирование таблицы`relation` по полю`attribute`. Аргумент`start_value` задает начальное значение,`interval` -- диапазон значений внутри одной секции,`premake` -- количество заранее создаваемых секций (если 0, то будет создана единственная секция).
71+
```
72+
create_range_partitions(
73+
relation TEXT,
74+
attribute TEXT,
75+
start_value ANYELEMENT,
76+
interval INTERVAL,
77+
premake INTEGER)
78+
```
79+
Аналогично предыдущей с тем лишь отличием, что данная функция предназначена для секционирования по полю типа`DATE` или`TIMESTAMP`.
80+
81+
###Утилиты
82+
```
83+
partition_data(parent text)
84+
```
85+
Копирует данные из родительской таблицы`parent` в дочерние секции.
86+
```
87+
create_hash_update_trigger(parent TEXT)
88+
```
89+
Создает триггер на UPDATE для HASH секций. По-умолчанию триггер на обновление данных не создается, т.к. это создает дополнительные накладные расходы. Триггер полезен только в том случае, когда меняется значение ключевого аттрибута.
90+
```
91+
create_hash_update_trigger(parent TEXT)
92+
```
93+
Аналогично предыдущей, но для RANGE секций.
94+
95+
###Управление секциями
96+
```
97+
split_range_partition(partition TEXT, value ANYELEMENT)
98+
```
99+
Разбивает RANGE секцию`partition` на две секции по значению`value`.
100+
```
101+
merge_range_partitions(partition1 TEXT, partition2 TEXT)
102+
```
103+
Объединяет две смежные RANGE секции. Данные из`partition2` копируются в`partition1`, после чего секция`partition2` удаляется.
104+
```
105+
append_partition(p_relation TEXT)
106+
```
107+
Добавляет новую секцию в конец списка секций. Диапазон значений устанавливается равным последней секции.
108+
```
109+
prepend_partition(p_relation TEXT)
110+
```
111+
Добавляет новую секцию в начало списка секций.
112+
```
113+
disable_partitioning(relation TEXT)
114+
```
115+
Отключает механизм секционирования`pg_pathman` для заданной таблицы и удаляет триггер на вставку. При этом созданные ранее секции остаются без изменений.
116+
117+
##Примеры использования
118+
###HASH
119+
Рассмотрим пример секционирования таблицы, используя HASH-стратегию на примере таблицы.
120+
```
121+
CREATE TABLE hash_rel (
122+
id SERIAL PRIMARY KEY,
123+
value INTEGER);
124+
INSERT INTO hash_rel (value) SELECT g FROM generate_series(1, 10000) as g;
125+
```
126+
Разобьем таблицу`hash_rel` на 100 секций по полю`value`:
127+
```
128+
SELECT create_hash_partitions('hash_rel', 'value', 100);
129+
```
130+
Перенесем данные из родительской таблицы в дочерние секции.
131+
```
132+
SELECT partition_data('hash_rel');
133+
```
134+
###RANGE
135+
Пример секционирования таблицы с использованием стратегии RANGE.
136+
```
137+
CREATE TABLE range_rel (
138+
id SERIAL PRIMARY KEY,
139+
dt TIMESTAMP);
140+
INSERT INTO range_rel (dt) SELECT g FROM generate_series('2010-01-01'::date, '2015-12-31'::date, '1 day') as g;
141+
```
142+
Разобьем таблицу на 60 секций так, чтобы каждая секция содержала данные за один месяц:
143+
```
144+
SELECT create_range_partitions('range_rel', 'dt', '2010-01-01'::date, '1 month'::interval, 59);
145+
```
146+
>Значение`premake` равно 59, а не 60, т.к. 1 секция создается независимо от значения`premake`
147+
148+
Перенесем данные из родительской таблицы в дочерние секции.
149+
```
150+
SELECT partition_data('range_rel');
151+
```
152+
Объединим секции первые две секции:
153+
```
154+
SELECT merge_range_partitions('range_rel_1', 'range_rel_2');
155+
```
156+
Разделим первую секцию на две по дате '2010-02-15':
157+
```
158+
SELECT split_range_partition('range_rel_1', '2010-02-15'::date);
159+
```
160+
Добавим новую секцию в конец списка секций:
161+
```
162+
SELECT append_partition('range_rel')
163+
```

‎contrib/pg_pathman/conf.add

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
shared_preload_libraries='pg_pathman'

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp