如何在不丢失任何项目的情况下处理巨大的结果集

How to process huge result set without missing any items

我有一个脚本,该脚本 运行 在我的数据库中的每个项目上都有一个函数来提取学术引文。数据库很大,所以脚本需要大约一周的时间才能运行。

在此期间,会在数据库中添加和删除项目。

数据库太大,无法完全拉入内存,所以我必须分块处理所有项目。

有没有办法确保当脚本完成时,所有项目都已处理?这是一个具有简单解决方案的模式吗?到目前为止,我的研究还没有发现任何有用的东西。

PS:锁定 table 一周不是一个选择!

我会将时间戳列 "modified_at" 添加到默认为空的 table。因此可以识别任何新项目。

然后您的脚本可以根据该列选择要处理的块。

update items
  set modified_at = current_timestamp
from (
  select id
  from items
  where modified_at is null
  limit 1000 --<<< this defines the size of each "chunk" that you work on 
) t
where t.id = items.id
returning items.*;

这将更新 1000 行尚未处理的行,并将 return 这些行放在一个语句中。然后,您的作业可以处理 returned 项目。

需要使用 modified_at = null 添加新行,您的脚本将在您下次 运行 时根据 where modified_at is null 条件选择它们。

如果您在处理项目时还更改了 项,则需要相应地更新modified_at。然后,在您的脚本中,您需要将处理的最后一次开始存储在某处。脚本的下一个 运行 可以 select 项目使用

处理
 where modified_at is null 
   or modified_at < (last script start time)

如果你只处理每个项目一次(然后再也不会),你真的不需要时间戳,一个简单的布尔值(例如 is_processed)也可以。