3. Пример секционирования
id title city
1 Велосипед Москва
2 Вафельница Санкт-Петербург
3 Фотоаппарат Москва
4 Контрабас Санкт-Петербург
id title city
1 Велосипед Москва
3 Фотоаппарат Москва
id title city
2 Вафельница Санкт-Петербург
4 Контрабас Санкт-Петербург
items
items_msc items_spb
5. Преимущества секционирования
● Рост производительности при условии, что
наиболее часто используемые данные
находятся в небольшом числе секций.
● Использование последовательного доступа к
небольшим секциям вместо индекса или
случайного доступа к одной большой таблице.
● Управление большими объемами данных.
● Редко используемые данные могут быть
вынесены на более дешевые и медленные
носители.
6. Когда нужно секционировать?
● Эмпирическое правило: размер таблицы
превышает размер физической памяти.
● Таблица содержит исторические данные, а
новые записи добавляются в последнюю
секцию.
● Содержимое таблицы должно быть
распределено между дисками или серверами.
8. Виды секционирования в PostgreSQL
● RANGE
CHECK(dt_created >= '2015-01-01' AND
dt_created < '2016-01-01')
● LIST
CHECK(city IN (‘Уфа’, ‘Оренбург’, ‘Челябинск’))
● HASH (?)
CHECK( id % 10 = 0)
…
CHECK( id % 10 = 9)
SELECT * FROM my_table
WHERE id = 5 AND (id % 10) = (5 % 10)
9. Проблемы
● Полный перебор при поиске подходящих
секций (constraint exclusion)
● Нет встроенной поддержки HASH-
секционирования
● Ручное управление секциями
10. Решение
Определить структуры данных, над которыми
можно выполнять эффективный поиск
RANGE
• бинарный поиск в сортированном массиве
• поиск в бинарном дереве
HASH, LIST
• хеш-таблица
O(log2
N)
≈ O(1)
12. Используемые средства
Hook-функции — лазейки, используемые для
внедрения в код СУБД:
• planner_hook
• set_rel_pathlist_hook
Path — прототип планов. Для каждой таблицы,
используемой в запросе, строятся
всевозможные способы обхода, из которых
выбирается лучший. На его основе строится
узел плана.
16. Cache
partitioning type RANGE
attribute dt_create
attribute type timestamp
children ■■■■■■■■■
min 2016-01-01 2016-02-01 2016-03-01 2016-04-01
max 2016-02-01 2016-03-01 2016-04-01 2016-05-01
child orders_1 orders_2 orders_3 orders_4
22. 0 1 2 3
min 2016-01-01 2016-02-01 2016-03-01 2016-04-01
max 2016-02-01 2016-03-01 2016-04-01 2016-05-01
child orders_1 orders_2 orders_3 orders_4
Пример
OR
AND
dt_created >= ‘2016-01-15’ dt_created < ‘2016-03-01’ dt_created = ‘2016-04-01’
23. 0 1 2 3
min 2016-01-01 2016-02-01 2016-03-01 2016-04-01
max 2016-02-01 2016-03-01 2016-04-01 2016-05-01
child orders_1 orders_2 orders_3 orders_4
Пример
OR
AND
dt_created >= ‘2016-01-15’ dt_created < ‘2016-03-01’ dt_created = ‘2016-04-01’
T T T T
24. 0 1 2 3
min 2016-01-01 2016-02-01 2016-03-01 2016-04-01
max 2016-02-01 2016-03-01 2016-04-01 2016-05-01
child orders_1 orders_2 orders_3 orders_4
Пример
OR
AND
dt_created >= ‘2016-01-15’ dt_created < ‘2016-03-01’ dt_created = ‘2016-04-01’
T T T T T T F F
25. 0 1 2 3
min 2016-01-01 2016-02-01 2016-03-01 2016-04-01
max 2016-02-01 2016-03-01 2016-04-01 2016-05-01
child orders_1 orders_2 orders_3 orders_4
Пример
OR
AND
dt_created >= ‘2016-01-15’ dt_created < ‘2016-03-01’ dt_created = ‘2016-04-01’
T T T T T T F F F F F T
26. 0 1 2 3
min 2016-01-01 2016-02-01 2016-03-01 2016-04-01
max 2016-02-01 2016-03-01 2016-04-01 2016-05-01
child orders_1 orders_2 orders_3 orders_4
Пример
OR
AND
dt_created >= ‘2016-01-15’ dt_created < ‘2016-03-01’ dt_created = ‘2016-04-01’
T T T T T T F F F F F T
T T F F
27. 0 1 2 3
min 2016-01-01 2016-02-01 2016-03-01 2016-04-01
max 2016-02-01 2016-03-01 2016-04-01 2016-05-01
child orders_1 orders_2 orders_3 orders_4
Пример
OR
AND
dt_created >= ‘2016-01-15’ dt_created < ‘2016-03-01’ dt_created = ‘2016-04-01’
T T T T T T F F F F F T
T T F F
T T F T
28. 0 1 2 3
min 2016-01-01 2016-02-01 2016-03-01 2016-04-01
max 2016-02-01 2016-03-01 2016-04-01 2016-05-01
child orders_1 orders_2 orders_3 orders_4
Пример
OR
AND
dt_created >= ‘2016-01-15’ dt_created < ‘2016-03-01’ dt_created = ‘2016-04-01’
P T T T T T F F F F F P
P T F F
P T F P
29. 0 1 2 3
P T F P
Plan:
orders_4
dt_created >= ‘2016-01-15’ dt_created = ‘2016-04-01’full scan
orders_2orders_1
30. HASH секционирование
OID Partitioning info
431287
431290
431295
431299
partitioning type HASH
attribute city_id
attribute type integer
children ■■■■■■■■■
37. Эксперимент для HASH
Время планирования в зависимости от количества секций
в разбиении
Таблица:
CREATE TABLE hash_test(id INTEGER);
Количество созданных секций:
2, 4, 8, 16, 32, 64, 128, 512, 1024, 2048
Количество запросов:
10000 на каждой конфигурации
EXPLAIN ANALYZE
SELECT * FROM hash_test
WHERE id = 10 AND (id%<N> = 10%<N>);
(где <N> - количество секций)
39. Эксперимент для RANGE
Время планирования в зависимости от количества секций
в разбиении
Таблица:
CREATE TABLE range_test(id INTEGER);
Количество созданных секций:
2, 4, 8, 16, 32, 64, 128, 512, 1024, 2048
Количество запросов:
10000 на каждой конфигурации
EXPLAIN ANALYZE
SELECT * FROM range_test
WHERE id = 10;
41. Эксперимент для RANGE
Время планирования в зависимости от количества
секций в плане
Таблица:
CREATE TABLE range_test(
id INTEGER,
dt TIMESTAMP);
Количество созданных секций:
1095
Количество секций, попадающих в план:
от 1 до 1095