У нас есть растущая база данных событий, каждое из которых имеет первичный ключ uuid. Только INSERTs
делается на этой event
таблице. Ни одна запись не обновляется и не удаляется.
Эта таблица является частью большой системы и не может быть изменена. Однако мне разрешено добавлять к нему индексы.
create table event (
id uuid primary key,
type varchar(50),
payload jsonb
);
insert into event (uuid, type, payload) values ($1, $2, $3);
События с указанными c types
должны агрегироваться постепенно. В прошлом я мог просто сделать большой материализованный взгляд. Но теперь объем такой, что я больше не могу этого делать, и мне придется обрабатывать события одно за другим. Фактически было бы желательно получить значение, близкое к реальному времени.
События, которые необходимо обработать, должны обрабатываться только один раз, в противном случае моя агрегация не работает.
Я рассмотрел следующие варианты:
- добавить триггер в мою таблицу
event
и скопировать события для обработки в другую таблицу, пока они не будут фактически обработаны. Я не хочу этого делать, потому что ошибка в триггере может помешать вставке в таблицу event
. Мы не можем проиграть ни одного события. - полагаться на временную метку / серийный номер, чтобы упорядочить записи. Все эти попытки приводили к пропущенным записям из-за других задержек в системе (например, сбои в сети).
Один простой способ достичь sh этой цели «обрабатывать ровно один раз» - хранить UUID каждого обработанного события в таблицу. Затем я мог бы запросить таблицу, чтобы проверить, было ли обработано определенное событие.
create table processed_event (
id uuid primary key
);
Но тогда это происходит: у меня есть таблица с uuids и индекс с такими же uuids. По сути, я только что продублировал свои данные. И на моем старом снимке (после полного вакуума) требуется значительный объем дискового пространства, около 2 ГБ.
objectname | objecttype | entries | size
--------------------------------------------------+------------+-------------+---------
processed_event | r | 2.49663e+07 | 1054 MB
processed_event_pkey | i | 2.49662e+07 | 751 MB
Так что я не уверен, как будет масштабироваться это решение. На данный момент, с производственной базой данных, это будет> 5 ГБ данных только для хранения обработанных событий.
Вопросы:
- Есть ли еще какие-либо Как я могу убедиться, что я не обрабатываю дважды одну и ту же запись?
- Есть ли шанс, что я смогу избавиться от таблицы
processed_event
и сохранить только индекс processed_event_pkey
? - Любое предложение ?
Решение
Полезны ответы Лоренца и Джеррада, приведенные ниже. Жаль, что я могу проверить только один ...
Вероятно, в итоге мы получим триггер для таблицы event
, который вставляет новые идентификаторы событий в таблицу processed_event
.
create table processed_event (
id uuid primary key,
processed_at timestamp
)
Пока событие не обработано, отметка времени будет нулевой.
Это позволит:
- быстрый выбор необработанных событий
- отладка / мониторинг ход обработки
- повторная обработка событий, если агрегаты изменяются после начальной обработки. Просто установите
processed_at
на ноль.