过滤并显示数据库审计/更改日志(活动流)

时间:2015-10-30 07:34:00

标签: postgresql database-design indexing sqlalchemy

我正在使用SQLAlchemy和PostgreSQL开发应用程序。系统用户修改8个左右表中的数据。考虑这个人为的示例模式:

enter image description here

我想将可见记录添加到系统中以记录已更改的内容,但不一定记录它的更改方式。例如:"用户A修改后的产品Foo","用户A添加了用户B"或"用户C购买了产品Bar"。所以基本上我想存储:

  1. 谁做出了改变
  2. 描述更改的消息
  3. 足以引用更改对象的信息,例如下订单时product_idcustomer_id,以便用户可以点击该实体
  4. 我想在每个用户登录应用程序时显示最近和相关的更改列表(有点像Facebook等主要时间轴)。我想存储订阅,以便用户可以订阅更改,例如"告诉我产品X何时被修改"或者"告诉我商店S中的任何产品何时被修改"。

    我见过audit trigger recipe,但我不确定它是我想要的。该审核触发器可以很好地完成录制更改,但是如何快速过滤它以显示用户最近的相关更改?我考虑的选项:

    • 在日志和订阅表中每个ID类型都有一列,每列都有一个索引
    • 使用全文搜索,将ID类型组合为tsvector
    • 使用hstore或json列作为ID,并以某种方式索引内容
    • 将引用存储为不带索引的URI(字符串),并按反向日期顺序遍历日志,使用应用程序逻辑按URI过滤

    任何见解都表示赞赏:)

    编辑我似乎正在谈论activity streamthis answer中按时间过滤的建议听起来不错。

1 个答案:

答案 0 :(得分:1)

由于对象都使用uuid enum字段,我想我会像这样创建活动表:

  • 具有对目标对象的通用引用,其中uuid列没有外键,text[]列指定它引用的对象类型。
  • 有一个数组列,用于存储目标对象及其父项的通用SELECT * FROM ( SELECT DISTINCT ON (activity.created, activity.id) * FROM activity LEFT OUTER JOIN unnest(activity.object_ref) WITH ORDINALITY AS act_ref ON true LEFT OUTER JOIN subscription ON subscription.object_id = act_ref.act_ref WHERE activity.created BETWEEN :lower_date AND :upper_date AND subscription.user_id = :user_id ORDER BY activity.created DESC, activity.id, act_ref.ordinality DESC ) AS sub WHERE sub.subscribed = true; (可能为unnest(...) WITH ORDINALITY)(例如父类别,商店和组织),并搜索数组以进行前进订阅。这样,父类别的订阅可以在一个步骤中匹配子项(非规范化)。
  • 在日期列上放置一个btree索引,并且(可能)在数组UUID列上放置一个GIN索引。

Entity diagram of activity and subscription tables

我可能会先按时间过滤以减少所需的搜索量。稍后,如果需要,我会看看使用GIN索引数组列(这部分回答了我的问题“是否有以灵活方式索引hstore的技巧?”)

更新这项运作良好。获取时间轴的SQL看起来像这样:

unnest

加入@>,按惯例排序,并在活动ID上选择不同,过滤掉在更深层次上 un 订阅的活动。如果您不需要这样做,那么您可以避免使用SELECT * FROM activity JOIN subscription ON activity.object_ref @> subscription.object_id WHERE subscription.user_id = :user_id AND activity.created BETWEEN :lower_date AND :upper_date ORDER BY activity.created DESC; 并使用数组包含title运算符,而不使用子查询:

activity

您也可以与其他对象表连接以获取对象标题 - 但我决定在{{1}}表中添加{{1}}列。这是非规范化的,但它不需要与许多表的复杂连接,并且它允许删除对象(可能是触发活动记录的操作)。