I w*_*ood 5 postgresql amazon-rds jooq sql-insert
我正在尝试做的事情:
我正在尝试将大约 200 万条记录从一个表移动到另一个表中。为此,我正在执行一个insert由查询提供的语句select。
insert into my_table (
select a, b, c
from my_other_table
where (condition)
)
Run Code Online (Sandbox Code Playgroud)
然而,在运行这个程序时,我总是出现内存不足的情况。
我的期望(以及为什么我感到困惑):
如果工作集大于内存所能容纳的大小,我完全认为 Postgres 会将页面缓冲到磁盘上并在幕后迭代地进行写入。
然而,所发生的情况是,它显然尝试将所有edselect内容读入内存,然后再将其填充到另一个表中。
即使在我们的大块 r5.2xl 实例上,它也会消耗所有内存,直到最终 OOM Killer 触发并且 Aurora 重新启动实例。
该图显示每次运行查询时,可用内存都会下降到零。内存备份是由于实例因 OOM 而被自动杀死并重新启动。
我的主要问题:
我尝试过的:
调整shared_buffers和work_mem参数。
Aurora 的默认shared_buffer值为我们的实例分配 20GB。我尝试将其调低至 10gb,然后调至 6.5gb(每次都重新启动),但无济于事。唯一的影响是使查询花费很长时间,并且在运行大约 30 分钟后最终仍然消耗所有可用内存。
我同样尝试将work_mem所有方式设置为允许的最小值,但这似乎对最终结果没有影响。
我可以做些什么来解决这个问题:
当然,我可以从客户端进行分页/批处理:
computeBatchOffsets(context).forEach(batchOffset ->
context.insertInto(BLAH)
.select(DSL.asterisk())
.from(FOO)
.limit(batchOffset)
.offset(batchOffset)
.execute()
Run Code Online (Sandbox Code Playgroud)
但是,除了比仅仅让数据库执行它要慢之外,它“感觉”像是数据库肯定能够在内部执行的操作。所以,我很困惑为什么我需要在客户端级别处理它。