Масштабирование PostgreSQL TRIGGER (s)

14

Как Postgres запускает механизм весов?

У нас большая установка PostgreSQL, и мы пытаемся реализовать систему, основанную на событиях, используя таблицы журналов и TRIGGER (s).

По сути, мы хотели бы создать TRIGGER для каждой таблицы, которую мы хотим получать для операции UPDATE / INSERT / DELETE. Как только этот триггер сработает, он выполнит функцию, которая просто добавит новую строку (кодирующую событие) в таблицу журнала, которую мы затем опросим из внешней службы.

Прежде чем идти в олл-ин с Postgres TRIGGER, нам хотелось бы узнать, как они масштабируются: сколько триггеров мы можем создать в одной установке Postgres? Влияют ли они на производительность запросов? Кто-нибудь раньше пробовал это?

Уго Матранголо
источник
Проверка PgQ может оказаться полезной, она использует триггеры C для регистрации событий модификации данных.
Дезсо
Посмотрите на прослушивание / уведомление, что вам могут вообще не понадобиться триггеры: postgresql.org/docs/current/static/sql-listen.html
a_horse_with_no_name

Ответы:

17

По сути, мы хотели бы создать TRIGGER для каждой таблицы, которую мы хотим получать для операции UPDATE / INSERT / DELETE. Как только этот триггер сработает, он выполнит функцию, которая просто добавит новую строку (кодирующую событие) в таблицу журнала, которую мы затем опросим из внешней службы.

Это довольно стандартное использование для триггера.

Прежде чем идти в олл-ин с Postgres TRIGGER, нам хотелось бы узнать, как они масштабируются: сколько триггеров мы можем создать в одной установке Postgres?

Если вы продолжите создавать их, в конечном итоге вам не хватит места на диске.

Там нет конкретного ограничения для триггеров.

Ограничения PostgreSQL документированы на странице about .

Влияют ли они на производительность запросов?

Это зависит от типа триггера, языка триггера и того, что делает триггер.

Простой BEFORE ... FOR EACH STATEMENTтриггер PL / PgSQL, который ничего не делает, имеет почти нулевые издержки.

FOR EACH ROWтриггеры имеют более высокие издержки, чем FOR EACH STATEMENTтриггеры. Масштабирование, очевидно, с учетом количества строк.

AFTERтриггеры дороже, чем BEFOREтриггеры, потому что они должны быть поставлены в очередь, пока оператор не завершит свою работу, а затем исполнится. Они не выводятся на диск, если очередь становится большой (по крайней мере, в 9.4 и ниже, может измениться в будущем), поэтому огромные AFTERочереди запуска могут привести к переполнению доступной памяти, что приведет к прерыванию оператора.

Триггер, который изменяет NEWстроку перед вставкой / обновлением, дешевле, чем триггер, который выполняет DML.

Конкретный вариант использования, который вы хотите, будет лучше работать с улучшением, которое может быть реализовано в PostgreSQL 9.5 (если нам повезет), где FOR EACH STATEMENTтриггеры могут видеть виртуальные OLDи NEWтаблицы. Это невозможно в текущих версиях PostgreSQL, поэтому вы должны использовать FOR EACH ROWтриггеры.

Кто-нибудь раньше пробовал это?

Конечно. Это довольно стандартное использование для триггеров, наряду с аудитом, проверкой работоспособности и т. Д.

Вы захотите изучить LISTENи NOTIFYнайти хороший способ разбудить вашего работника, когда произойдут изменения в таблице задач.

Вы уже делаете самое важное, избегая общения с внешними системами напрямую от триггеров. Это имеет тенденцию быть проблематичным для производительности и надежности. Люди часто пытаются сделать что-то вроде отправки почты прямо из триггера, и это плохие новости.

Крейг Рингер
источник
1

Это немного запоздалый ответ, но он может быть полезен для будущих читателей

Сейчас (в версиях 10,11,12) нам не нужно хранить одни и те же данные дважды (в WAL PG и вручную). Мы можем использовать механику Postgre Logical Decoding ( такую же, как логическая репликация), чтобы отслеживать все или некоторые изменения в наших данных (или отправлять эти события в некоторую очередь, например, kafka, для последующего анализа).

Александр латушкин
источник