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

Commit58e6a23

Browse files
committed
initial commit
0 parents  commit58e6a23

16 files changed

+4103
-0
lines changed

‎.gitignore

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

‎Makefile

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# contrib/pathman/Makefile
2+
3+
MODULE_big = pathman
4+
OBJS = init.o pathman.o dsm_array.o rangeset.o pl_funcs.o$(WIN32RES)
5+
6+
EXTENSION = pathman
7+
EXTVERSION = 0.1
8+
DATA_built =$(EXTENSION)--$(EXTVERSION).sql
9+
PGFILEDESC = "pathman - partitioning tool"
10+
11+
REGRESS = 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/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$^>$@

‎README.md

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
#pathman
2+
3+
The`pathman` module provides optimized partitioning mechanism and functions to manage partitions.
4+
5+
##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+
CHECK ( id >= 100 AND id < 200 )
17+
CHECK ( id >= 200 AND id < 300 )
18+
```
19+
20+
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.
21+
22+
The`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`pathman` module caches information about child partitions in shared memory in form convenient to perform rapid search. When user executes SELECT query pathman analyzes conditions tree looking for conditions like:
23+
24+
```
25+
VARIABLE OP CONST
26+
```
27+
where`VARIABLE` is partitioning key,`OP` is comparison operator (supported operators are =, <, <=, >, >=),`CONST` is scalar value. For example:
28+
29+
```
30+
WHERE id = 150
31+
```
32+
33+
Based on partitioning type and operator the`pathman` searches corresponding partitions and builds the plan.
34+
35+
##Installation
36+
37+
To install pathman run in psql:
38+
```
39+
CREATE SCHEMA pathman;
40+
CREATE EXTENSION pathman SCHEMA pathman;
41+
```
42+
Then modify shared_preload_libraries parameter in postgres.conf as following:
43+
```
44+
shared_preload_libraries = 'pathman'
45+
```
46+
It will require to restart the PostgreSQL instance.
47+
48+
##Pathman Functions
49+
50+
###Partitions Creation
51+
```
52+
create_hash_partitions(
53+
relation TEXT,
54+
attribute TEXT,
55+
partitions_count INTEGER)
56+
```
57+
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.
58+
59+
```
60+
create_range_partitions(
61+
relation TEXT,
62+
attribute TEXT,
63+
start_value ANYELEMENT,
64+
interval ANYELEMENT,
65+
premake INTEGER)
66+
```
67+
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).
68+
```
69+
create_range_partitions(
70+
relation TEXT,
71+
attribute TEXT,
72+
start_value ANYELEMENT,
73+
interval INTERVAL,
74+
premake INTEGER)
75+
```
76+
Same as above but suitable for`DATE` and`TIMESTAMP` partitioning keys.
77+
78+
###Utilities
79+
```
80+
partition_data(parent text)
81+
```
82+
Copies data from parent table to its partitions.
83+
```
84+
create_hash_update_trigger(parent TEXT)
85+
```
86+
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.
87+
```
88+
create_hash_update_trigger(parent TEXT)
89+
```
90+
Same as above for RANGE sections.
91+
92+
###Partitions management
93+
```
94+
split_range_partition(partition TEXT, value ANYELEMENT)
95+
```
96+
Splits RANGE`partition` in two by`value`.
97+
```
98+
merge_range_partitions(partition1 TEXT, partition2 TEXT)
99+
```
100+
Merge two adjacent RANGE partitions. Data from`partition2` is copied to`partition1`. Then the`partition2` is removed.
101+
```
102+
append_partition(p_relation TEXT)
103+
```
104+
Appends new partition with the range equal to the range of the previous partition.
105+
```
106+
prepend_partition(p_relation TEXT)
107+
```
108+
Prepends new partition with the range equal to the range of the first partition.
109+
```
110+
disable_partitioning(relation TEXT)
111+
```
112+
Disables`pathman` partitioning mechanism for the specified parent table and removes an insert trigger. Partitions itself remain unchanged.
113+
114+
##Examples
115+
###HASH
116+
Consider an example of HASH partitioning. First create a table with some integer column:
117+
```
118+
CREATE TABLE hash_rel (
119+
id SERIAL PRIMARY KEY,
120+
value INTEGER);
121+
INSERT INTO hash_rel (value) SELECT g FROM generate_series(1, 10000) as g;
122+
```
123+
Then run create_hash_partitions() function with appropriate arguments:
124+
```
125+
SELECT create_hash_partitions('hash_rel', 'value', 100);
126+
```
127+
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:
128+
```
129+
SELECT partition_data('hash_rel');
130+
```
131+
###RANGE
132+
Consider an example of RANGE partitioning. Create a table with numerical or date or timestamp column:
133+
```
134+
CREATE TABLE range_rel (
135+
id SERIAL PRIMARY KEY,
136+
dt TIMESTAMP);
137+
INSERT INTO range_rel (dt) SELECT g FROM generate_series('2010-01-01'::date, '2015-12-31'::date, '1 day') as g;
138+
```
139+
Run create_range_partitions() function to create partitions so that each partition would contain data for one month:
140+
```
141+
SELECT create_range_partitions('range_rel', 'dt', '2010-01-01'::date, '1 month'::interval, 59);
142+
```
143+
It will create 60 partitions (one partition is created regardless of`premake` parameter). Now move data from the parent to partitions.
144+
```
145+
SELECT partition_data('range_rel');
146+
```
147+
To merge to adjacent partitions run merge_range_partitions() function:
148+
```
149+
SELECT merge_range_partitions('range_rel_1', 'range_rel_2');
150+
```
151+
To split partition use split_range_partition() function:
152+
```
153+
SELECT split_range_partition('range_rel_1', '2010-02-15'::date);
154+
```
155+
Now let's create new partition. You can use append_partition() or prepend_partition() functions:
156+
```
157+
SELECT append_partition('range_rel');
158+
SELECT append_partition('range_rel');
159+
```
160+
161+
##Author
162+
Ildar Musin <i.musin@postgrespro.ru> Postgres Professional Ltd., Russia
163+
This module is sponsored by Postgres Professional Ltd., Russia

‎README.rus.md

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

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp