如何在不丢失任何项目的情况下处理巨大的结果集
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
)也可以。
我有一个脚本,该脚本 运行 在我的数据库中的每个项目上都有一个函数来提取学术引文。数据库很大,所以脚本需要大约一周的时间才能运行。
在此期间,会在数据库中添加和删除项目。
数据库太大,无法完全拉入内存,所以我必须分块处理所有项目。
有没有办法确保当脚本完成时,所有项目都已处理?这是一个具有简单解决方案的模式吗?到目前为止,我的研究还没有发现任何有用的东西。
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
)也可以。