存储最新事件数据的最佳方式

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