存储最新事件数据的最佳方式
best way to store latest event data
我们正在使用基于事件的系统,其中使用 postgres 数据库来存储事件审计。目前,为了存储任何事件的最新条目,我们正在使用 postgres MATERIALIZED VIEW。对于任何修改数据的事件,我们更新主事件审核 table 并刷新 MATERIALIZED VIEW,但这是非常耗时的。我们使用下面的 python 代码来刷新视图,但它只是删除旧视图并重新创建它,这很耗时
await connection_pool.execute(
"REFRESH MATERIALIZED VIEW CONCURRENTLY events_current"
)
我想这不是正确的处理方式,我的方法是创建一个新的 table 并在那里保留事件的最新数据。请让我知道这是否合适,或者是否有更好的方法。
如果需要任何进一步的信息,请告诉我。
实体化视图不是一个糟糕的解决方案,但前提是您可以将其视为“时间点”(工作日的开始,或过去 3 小时内,...)。对于“此刻”的要求,这不是一个好的解决方案。你的好像是后者。
您最好的选择就是创建一个获取最新数据的视图。如果那不可行,由于审计事件的大小,则需要寻找其他地方。我不喜欢创建 table 来包含最新数据。那将是复制数据,而复制的数据必然会有所不同。但是我想到了一个轻微的转折:创建一个只包含事件 ID 和 event_audit 日志 ID 的 table,只维护最后一个审计 ID。没有你完整的 table 定义 (ddl),我只能展示一个骨架设置,但你应该明白了。
create table event_last_audits(
event_id integer
, ea_id integer
, constraint last_event_audits_pk primary key (event_id)
, constraint last_event_audits_2fk
foreign key (ea_id)
references event_audits(ea_id)
);
Yon 然后可以在同一个触发器中维护 event_audit 和 event_last_audit。类似于:
create or replace function audit_events()
returns trigger
language plpgsql
as $$
begin
with audit_rec( event_id, ea_id) as
( insert into event_audits(event_id, dml_action,old_status)
select new.event_id
, tg_op
, case when tg_op='INSERT'
then null
else old.status
end
returning event_id, ea_id
)
insert into event_last_audits(event_id, ea_id)
select event_id, ea_id
from audit_rec
on conflict (event_id)
do update
set ea_id = excluded.ea_id;
return new;
end; $$;
create trigger audit_events_aiur
after insert or update on events
for each row
execute function audit_events();
参见demo。
我们正在使用基于事件的系统,其中使用 postgres 数据库来存储事件审计。目前,为了存储任何事件的最新条目,我们正在使用 postgres MATERIALIZED VIEW。对于任何修改数据的事件,我们更新主事件审核 table 并刷新 MATERIALIZED VIEW,但这是非常耗时的。我们使用下面的 python 代码来刷新视图,但它只是删除旧视图并重新创建它,这很耗时
await connection_pool.execute(
"REFRESH MATERIALIZED VIEW CONCURRENTLY events_current"
)
我想这不是正确的处理方式,我的方法是创建一个新的 table 并在那里保留事件的最新数据。请让我知道这是否合适,或者是否有更好的方法。
如果需要任何进一步的信息,请告诉我。
实体化视图不是一个糟糕的解决方案,但前提是您可以将其视为“时间点”(工作日的开始,或过去 3 小时内,...)。对于“此刻”的要求,这不是一个好的解决方案。你的好像是后者。
您最好的选择就是创建一个获取最新数据的视图。如果那不可行,由于审计事件的大小,则需要寻找其他地方。我不喜欢创建 table 来包含最新数据。那将是复制数据,而复制的数据必然会有所不同。但是我想到了一个轻微的转折:创建一个只包含事件 ID 和 event_audit 日志 ID 的 table,只维护最后一个审计 ID。没有你完整的 table 定义 (ddl),我只能展示一个骨架设置,但你应该明白了。
create table event_last_audits(
event_id integer
, ea_id integer
, constraint last_event_audits_pk primary key (event_id)
, constraint last_event_audits_2fk
foreign key (ea_id)
references event_audits(ea_id)
);
Yon 然后可以在同一个触发器中维护 event_audit 和 event_last_audit。类似于:
create or replace function audit_events()
returns trigger
language plpgsql
as $$
begin
with audit_rec( event_id, ea_id) as
( insert into event_audits(event_id, dml_action,old_status)
select new.event_id
, tg_op
, case when tg_op='INSERT'
then null
else old.status
end
returning event_id, ea_id
)
insert into event_last_audits(event_id, ea_id)
select event_id, ea_id
from audit_rec
on conflict (event_id)
do update
set ea_id = excluded.ea_id;
return new;
end; $$;
create trigger audit_events_aiur
after insert or update on events
for each row
execute function audit_events();
参见demo。