strategies to prevent OOM when retrieving large field values
维护者通常 1 天内回复
还没有人认领这个 Issue。
评估
- 难度
- 5/5
- 预计耗时
- 一周以上
- 新手友好度
- 25/100
- Issue 类型
- 功能
- 描述清晰度
- 需要澄清
- 活跃度
- 停滞
- 技术栈
- javascript, postgresql
调研方向
从重复的 issue #2336 和提供的 cursor 复现脚本开始;审查 pg-cursor 和 Pool 连接层级如何参与其中。在决定这是否属于 pg 或应作为单独的贡献之前,先定义所需的中止边界和可观察的完成标准。
由索引模型根据 Issue 内容生成。
描述
First, thank you for maintaining the pg library. I'm having an issue dealing with large field values that I'd like to get community guidance on.
Problem Description
When working with PostgreSQL tables that contain very large field values (text columns with hundreds of MB or more), we face a risk of out-of-memory (OOM) errors. Even when using pagination techniques like cursors, the library loads entire rows into memory, which becomes problematic with extremely large fields.
Our ideal solution would be a way to set a maximum threshold for query result size and automatically abort when exceeded, preventing memory issues.
Reproduction Case
Here's a minimal script demonstrating the issue:
const pg = require('pg')
async function demonstrateMemoryIssue() {
// Create pool
const pool = new pg.Pool({
connectionString: 'postgresql://postgres:postgres@localhost:5432/postgres',
})
try {
// Create test table and insert a large row
await pool.query('DROP TABLE IF EXISTS memory_test')
await pool.query(`
CREATE TABLE memory_test (
id SERIAL PRIMARY KEY,
name TEXT,
large_data1 TEXT,
large_data2 TEXT,
large_data3 TEXT,
large_data4 TEXT,
large_data5 TEXT,
large_data6 TEXT,
large_data7 TEXT,
large_data8 TEXT,
large_data9 TEXT,
large_data10 TEXT,
large_data11 TEXT,
large_data12 TEXT,
large_data13 TEXT,
large_data14 TEXT,
large_data15 TEXT,
large_data16 TEXT,
large_data17 TEXT,
large_data18 TEXT,
large_data19 TEXT,
large_data20 TEXT
)
`)
// Insert a single row with 20 columns of 500MB each (total 10GB)
console.log('Inserting large rows...')
await pool.query(`
INSERT INTO memory_test (
name,
large_data1, large_data2, large_data3, large_data4, large_data5,
large_data6, large_data7, large_data8, large_data9, large_data10,
large_data11, large_data12, large_data13, large_data14, large_data15,
large_data16, large_data17, large_data18, large_data19, large_data20
)
VALUES (
'Ultra Large Row',
repeat('A', 500 * 1024 * 1024), repeat('B', 500 * 1024 * 1024),
repeat('C', 500 * 1024 * 1024), repeat('D', 500 * 1024 * 1024),
repeat('E', 500 * 1024 * 1024), repeat('F', 500 * 1024 * 1024),
repeat('G', 500 * 1024 * 1024), repeat('H', 500 * 1024 * 1024),
repeat('I', 500 * 1024 * 1024), repeat('J', 500 * 1024 * 1024),
repeat('K', 500 * 1024 * 1024), repeat('L', 500 * 1024 * 1024),
repeat('M', 500 * 1024 * 1024), repeat('N', 500 * 1024 * 1024),
repeat('O', 500 * 1024 * 1024), repeat('P', 500 * 1024 * 1024),
repeat('Q', 500 * 1024 * 1024), repeat('R', 500 * 1024 * 1024),
repeat('S', 500 * 1024 * 1024), repeat('T', 500 * 1024 * 1024)
)
`)
console.log('Fetching all rows...')
// Even with a cursor, this will cause memory issues
const client = await pool.connect()
// Try with cursor approach
const Cursor = require('pg-cursor')
const cursor = client.query(new Cursor('SELECT * FROM memory_test'))
// Read in small batches (still causes memory issues)
cursor.read(10, (err, rows) => {
if (err) {
console.error('Error reading rows:', err)
} else {
console.log(`Retrieved ${rows.length} rows`)
console.log(rows)
process.exit(0)
}
})
} catch (error) {
console.error('Error:', error)
}
}
demonstrateMemoryIssue()
// run with: /usr/bin/time -l node script.js
Attempted Solutions
I've tried:
- Using cursors with small batch sizes, but as we see, cusor work row by row, and a single row could be gigabytes large not preventing the OOM of the program
- Try to plug into
pgevents to keep track of the current query buffer size (couldn't find a way to do this)
Questions
- Is there a recommended approach to cap the maximum data size returned by a query to prevent OOM error within the caller program, and keep any query result size bellow a specific amount of memory before gracefully aborting ?
Thank you for the time you'll take answering my question and pointing me in the right direction.
Edit: After searching in older issues, I discovered that this issue is actually a duplicate of: https://github.com/brianc/node-postgres/issues/2336.
In addition to what was mentioned there, my use case involves an application where the server running the query and the queried database belong to different actors.
If there is not any new known way to handle this, and if the community is still open to reviewing contributions along those lines, I could try to develop a solution for this use case by integrating at the pool connection level, as mentioned in the comments.
- 主要语言
- JavaScript
- 星标
- 13.2k
- 派生
- 1.4k
- 平均合并
- 6 天 15 小时
- 30 天内合并 PR
- 6
环境准备
我们还没有检查这个项目的环境配置文件。先看它的 README,通用步骤见我们的新手贡献指南。
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
brianc/node-postgres 的其他 Issue
-
难度 2/5 1-3 小时 新手友好度 68/100
brianc/node-postgres#3770 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 75/100
brianc/node-postgres#3716 · 1 条评论 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 68/100
brianc/node-postgres#3631 · 1 条评论 ·
维护者通常 1 天内回复
-
难度 1/5 1-3 小时 新手友好度 62/100
brianc/node-postgres#2857 ·
维护者通常 1 天内回复
-
难度 1/5 1 小时以内 新手友好度 68/100
brianc/node-postgres#2433 ·
维护者通常 1 天内回复
查看 brianc/node-postgres 的全部 Issue
相似的 Issue
-
Complexity: Small P-Feature: Projects page ready for merge team role: back end/devOps role: front end size: 0.25pt
难度 1/5 1-3 小时 新手友好度 88/100
维护者通常 1 天内回复
-
难度 1/5 1 小时以内 新手友好度 67/100
bellingcat/toolkit#905 ·
-
self-care self-care:docs-build-time-investigator
难度 2/5 半天 新手友好度 76/100
githubnext/gh-aw-cao#14191 ·
维护者通常 1 天内回复
-
effort:low impact:medium RAG status: auto-triaged
难度 2/5 1-3 小时 新手友好度 84/100
mastra-ai/mastra#25229 · 2 条评论 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 88/100
sugarlabs/musicblocks#8984 ·
维护者通常 1 天内回复