我在 PostgreSQL 9.2 中有一个表,它记录名为 user_login_session 的登录会话。该表包含 user_id、start_timestamp 和 end_timestamp 列等。随着我的系统越来越受欢迎,这张表已经开始增长,我现在无法清除旧记录。
我已经在这个表上定义了一个索引,但我担心它会随着时间的推移而增长。是否可以定义一个索引,它只保留每个用户 ID 的最新登录会话行的句柄?较旧的行不会在操作上访问。
这是一个典型的分区案例。
当您插入新记录时,让触发器从user_login_session_latest子表中删除旧记录并将其插入到user_login_session_history子表中。让它们都从一个空的顶级user_login_session表继承,这样您仍然可以透明地查询这两个表。您将需要一个额外的触发器维护列is_latest来进行分区,因为您无法在引用其他行的条件上进行约束排除。
部分索引可以工作,但不如您希望的那样好;很难根据“最新”的概念编写部分索引(您需要一个应用程序来设置标志),并且它可能不会像您期望的那样提升事物。部分索引指向一个页面,但如果该页面包含 10 个旧记录和一个新记录,您可能不会获得那么多;您需要定期CLUSTER查看桌子才能看到很多好处。分区将是一个更好的选择。
或者,您可以使用触发器或应用程序逻辑维护另一个表中“最新”用户的物化视图。为此,我通常更喜欢使用分区而不是物化视图。
如果正在进行大量更新/删除,请记住调整 autovacuum 以非常频繁地清理您的表。