45
Долгожданный релиз pg_pathman Дмитрий Иванов, Александр Коротков

Долгожданный релиз pg_pathman 1.0 / Александр Коротков, Дмитрий Иванов (Postgres Professional)

  • Upload
    ontico

  • View
    144

  • Download
    3

Embed Size (px)

Citation preview

Page 1: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

Долгожданный релиз pg_pathmanДмитрий Иванов, Александр Коротков

Page 2: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

Так зачем секционировать?

• Управление большими объемами данных• Быстрые запросы к наиболее используемым секциям

(локальность данных)• Хранение старых данных на медленных носителях или

отдельных серверах (FDW)• Pagination без OFFSET + LIMIT• Ротация данных при помощи секций

Page 3: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

• Таблица содержит архивные данные, в последнюю секцию добавляются новые данные

• Содержимое таблицы должно быть распределено между дисками или серверами (шардинг)

• Хочется ускорить запросы к определенным срезам данных

Когда нужно секционировать?

Page 4: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

Старый добрый метод

CREATE TABLE partitioned (val INT);

CREATE TABLE partitioned_1 (LIKE partitioned INCLUDING ALL)

INHERITS (partitioned);

ALTER TABLE partitioned_1 ADD CHECK (val >= 1 AND val < 100);

Page 5: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

Минусы

• Много ручной работы (управление секциями)• Полный перебор секций при планировании• Отсутствие оптимизаций во время исполнения• Нет встроенной поддержки HASH секционирования• Не копируются foreign keys родителя• “Интересные” проблемы с ACL (привилегии)

Page 6: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

Решение

• Выбрать какое-нибудь расширение для автоматизации рутины (не решает проблему с планированием)

• Попробовать написать свое :)

Page 7: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

pg_pathman - это:

• Поддержка HASH и RANGE секционирования• Автоматическое + ручное управление секциями• Улучшенное планирование запросов• RuntimeAppend - выбор секции во время исполнения • PartitionFilter - INSERT без триггеров• Перехват оператора COPY FROM/TO• Неблокирующее конкурентное секционирование• Поддержка FDW

Page 8: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

Основные элементы API

• Создание секций (add, attach, append, prepend)• Управление созданными секциями (merge, split, drop)• Генерация check constraints и триггеров для UPDATE• Установка обработчиков создания секций• Представление (view) с информацией о секциях• Представление (view) с перечнем задач конкурентного

секционирования• Таблица для хранения опциональных настроек

Page 9: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

Этапы выполнения запроса

Parser Rewriter Planner Executor

Page 10: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

RuntimeAppend(узел исполнения)

PartitionFilter(узел исполнения)

условия WHERE(исключение секций)

Page 11: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

Обработка условий (WHERE)

1. Механизм constraint exclusion в PostgreSQL не упрощает условия WHERE, которые попадают в секции. Они передаются “как есть”.

2. pg_pathman упрощает условия WHERE, которые попадают в каждую конкретную секцию.

3. Рассмотрим, как pg_pathman справляется с этим, на примере. Пусть данные разбиты на 6 секций по колонке ts. Каждая секция – один месяц начиная с 01.2016.

Page 12: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

SELECT * FROM test WHERE (ts >= '2015-02-01' AND ts < '2015-03-15') OR (ts >= '2015-05-15' AND ts < '2015-07-01');

Page 13: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

OR

AND AND

ts >= ‘2016-02-01’ ts < ‘2016-03-15’ ts >= ‘2016-05-15’ ts < ‘2016-07-01’

Page 14: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

OR

AND AND

ts >= ‘2016-02-01’ ts < ‘2016-03-15’ ts >= ‘2016-05-15’ ts < ‘2016-07-01’

F T T T T T T T M F F F

Page 15: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

OR

AND AND

ts >= ‘2016-02-01’ ts < ‘2016-03-15’ ts >= ‘2016-05-15’ ts < ‘2016-07-01’

F T T T T T T T M F F F F F F F M T T T T T T T

Page 16: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

OR

AND AND

ts >= ‘2016-02-01’ ts < ‘2016-03-15’ ts >= ‘2016-05-15’ ts < ‘2016-07-01’

F T T T T T T T M F F F F F F F M T T T T T T T

F F F F M TF T M F F F

Page 17: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

OR

AND AND

ts >= ‘2016-02-01’ ts < ‘2016-03-15’ ts >= ‘2016-05-15’ ts < ‘2016-07-01’

F T T T T T T T M F F F F F F F M T T T T T T T

F F F F M TF T M F F F

F T M F M T

Page 18: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

EXPLAIN SELECT * FROM test WHERE (ts >= '2015-02-01' AND ts < '2015-03-15') OR (ts >= '2015-05-15' AND ts < '2015-07-01'); QUERY PLAN-------------------------------------------------------------------------------- Append (cost=0.00..3248.59 rows=0 width=0) -> Seq Scan on test_2 (cost=0.00..780.20 rows=0 width=0) -> Index Scan using test_3_ts_idx on test_3 (cost=0.29..767.99 rows=0 width=0) Index Cond: (ts < '2015-03-15 00:00:00'::timestamp without time zone) -> Seq Scan on test_5 (cost=0.00..864.40 rows=0 width=0) Filter: (ts >= '2015-05-15 00:00:00'::timestamp without time zone) -> Seq Scan on test_6 (cost=0.00..836.00 rows=0 width=0)(7 rows)

Page 19: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

AppendSeqScan

21

28

10

21

14

10

10

14

Page 20: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

AppendSeqScan

21

28

10

21

14

10

10

14 [10, 21)

[21, 31)

Page 21: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

AppendSeqScan

10

21

14

10

10

14 [10, 21)

[21, 31)28

21

Page 22: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

RuntimeAppend

• Выбирает только те секции, которые подходят под условия (WHERE) в данный момент времени (на этапе исполнения)

• Умеет вычислять условия с параметрами ($N)• Побочный эффект: EXPLAIN (без ANALYZE) показывает

всех детей, так как мы должны запланировать все сканы до стадии исполнения

Page 23: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

RuntimeAppendSeqScan

10

21

14

10

10

14 [10, 21)

Page 24: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

RuntimeAppendSeqScan

10

21

14

25

27

21

[21, 31)

Page 25: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

RuntimeAppendSeqScan

10

21

14

10

10

14 [10, 21)

Page 26: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

SELECT * FROM partitioned_table

WHERE id = (SELECT * FROM some_table LIMIT 1);

SELECT * FROM partitioned_table

WHERE id = ANY (SELECT * FROM some_table LIMIT 4);

SELECT * FROM partitioned_table

JOIN some_table USING (id);

Page 27: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

Было:

EXPLAIN (COSTS OFF)

INSERT INTO partitioned_table

SELECT generate_series(1, 10), random();

QUERY PLAN

-----------------------------------------

Insert on partitioned_table

-> Subquery Scan on “*SELECT*”

-> Result

(3 rows)

PartitionFilter

Стало:

EXPLAIN (COSTS OFF)

INSERT INTO partitioned_table

SELECT generate_series(1, 10), random();

QUERY PLAN

-----------------------------------------

Insert on partitioned_table

-> Custom Scan (PartitionFilter)

-> Subquery Scan on “*SELECT*”

-> Result

(4 rows)

Page 28: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

PartitionFilter

INSERT

SubPlan(данные)

PartitionFilter

Page 29: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

PartitionFilter

INSERT

SubPlan(данные)

PartitionFilter

Page 30: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

PartitionFilter

INSERT

SubPlan(данные)

PartitionFilter

секция #1 [1, 101) секция #2 [101, 201) секция #3 [201, 301) секция #4 [301, 401) …

(схема партицирования)

Page 31: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

PartitionFilter

INSERT

SubPlan(данные)

PartitionFilter

секция #1 [1, 101) секция #2 [101, 201) секция #3 [201, 301) секция #4 [301, 401) …

(схема партицирования)

текущая таблица

Page 32: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

PartitionFilter

INSERT

SubPlan(данные)

PartitionFilter

выбранная секция

Page 33: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

PartitionFilter

INSERT

SubPlan(данные)

PartitionFilter

выбранная секция

Page 34: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

Плюсы PartitionFilter

• Быстрая вставка данных (сравнимо с обычной таблицей)• Поддержка предложения RETURNING *• Как следствие, корректно отображается число

вставленных строк• Поддержка триггеров

Page 35: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

INSERT INTO journal (dt, level, msg)

VALUES ('2016-12-31', random(), 'test')

RETURNING *;

id | dt | level | msg

---------+-----------------------+-------+------

1051202 | 2016-12-31 00:00:00 | 0 | test

(1 row)

INSERT 0 1

Page 36: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

COPY journal TO stdout;

1051203 2016-12-31 00:00:00 1 test

COPY journal FROM '/home/dmitry/journal.sql';

PATHMAN COPY 1

SELECT * FROM ONLY journal;

id | dt | level | msg

----+----+-------+-----

(0 rows)

Page 37: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

Бенчмарки

CREATE TABLE journal (

id SERIAL PRIMARY KEY ,

dt TIMESTAMP NOT NULL ,

level INTEGER,

msg TEXT);

CREATE INDEX journal_dt_idx ON journal (dt);

/* разбиваем на 366 секций, по 1 на день, затем заполняем данными: */

INSERT INTO journal (dt, level, msg) SELECT g, random() * 6, md5(g:: TEXT)

FROM generate_series( '2016-01-01'::DATE, '2016-12-31'::DATE, '30 seconds') as g;

Page 38: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)
Page 39: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)
Page 40: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)
Page 41: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)
Page 42: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

Бенчмарки - RuntimeAppend

CREATE TABLE rappend_test(

id INT NOT NULL,

val REAL,

comment TEXT);

CREATE INDEX ON rappend_test (id, comment);

/* разбиваем, заполняем данными */

SELECT create_range_partitions( 'rappend_test', 'id', 1, W, N);

INSERT INTO rappend_test select g, random(), g:: TEXT FROM generate_series(1, (1E8)) AS g;

Page 43: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

(500 partitions)

Page 44: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

(1000 partitions)

Page 45: Долгожданный релиз pg_pathman 1.0 / Александр Коротков,  Дмитрий Иванов (Postgres Professional)

Выводы

• pg_pathman даёт достаточно богатую функциональность. И гораздо

более высокую производительность, чем все другие расширения,

основанные на constraint exclusion.

• pg_pathman’ом можно пользоваться уже сейчас. Мы знаем, что то там,

то тут баги, но реагируем оперативно!

• Декларативный синтаксис будет в 10 (очень надеемся!). Но всех фич

pg_pathman он достигнет (самое раннее) к 11 (2018 г.).

• Как только с декларативным синтаксисом будут решены основные

вопросы, мы будем портировать свои фичи туда.