You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Node.js读取大文本文件并高效插入PostgreSQL数据库?

优化Node.js批量插入PostgreSQL的性能方案

针对大文件数据插入的性能问题,原代码的核心瓶颈在于单条数据高频插入和一次性加载超大文件,以下是具体优化方案:

原代码的性能痛点

  1. 数据库交互开销过大:每条数据单独执行INSERT,频繁的网络往返、事务初始化和提交占了绝大多数耗时。
  2. 内存资源浪费:fs.readFileSync直接把50万行文件全部读入内存,既占用大量内存,还会阻塞Node.js事件循环。
  3. 冗余IO拖慢速度:每条插入都打印日志,大量控制台输出额外消耗系统资源。
  4. 数据分割逻辑瑕疵:初始循环中i%10===0会先推入空数组,导致第一条数据无效,还可能打乱字段对应关系。

优化后的实现代码

const fs = require('fs');
const readline = require('readline');
const { Client } = require('pg');

// 数据库连接配置
const client = new Client({
  host: '你的数据库地址',
  port: 5432,
  user: '用户名',
  password: '密码',
  database: '数据库名'
});

// 批量插入批次大小,可根据服务器性能调整(建议1000-5000)
const BATCH_SIZE = 1000;
let batchData = [];

// 批量插入函数
const insertBatch = async () => {
  if (batchData.length === 0) return;

  try {
    // 构建多行INSERT语句,处理单引号转义以避免SQL注入
    const valueStrings = batchData.map(row => 
      `(${row.map(val => `'${val.replace(/'/g, "''")}'`).join(',')})`
    ).join(',');
    
    const sql = `INSERT INTO requirement(container, module, mod_devdate, part_no, qty, tapdate, tap_qty, taptime, sup_cd, namc_id) VALUES ${valueStrings}`;
    await client.query(sql);
    
    console.log(`已插入 ${batchData.length} 条数据`);
    batchData = [];
  } catch (err) {
    console.error('批量插入失败:', err);
    throw err;
  }
};

// 流式读取并处理文件
const processDataFile = async () => {
  await client.connect();

  const rl = readline.createInterface({
    input: fs.createReadStream('data.txt', 'utf-8'),
    crlfDelay: Infinity // 兼容所有换行格式
  });

  for await (const line of rl) {
    // 按|分割字段,保留空白内容
    const fields = line.split('|');
    // 确保字段数为10,不足的补空字符串
    while (fields.length < 10) fields.push('');
    // 清理字段中的控制字符,保留原有空白内容
    const processedFields = fields.slice(0,10).map(f => f.replace(/\x00|\r\n/g, ''));
    
    batchData.push(processedFields);

    // 达到批次大小则执行插入
    if (batchData.length >= BATCH_SIZE) {
      await insertBatch();
    }
  }

  // 处理剩余的不足一批的数据
  await insertBatch();
  await client.end();
  console.log('所有数据插入完成');
};

processDataFile().catch(err => console.error('处理流程失败:', err));

进阶优化建议

  • 使用COPY命令:PostgreSQL的COPY FROM是批量插入效率最高的方式,适合超大规模数据。可以将每行转换为CSV格式后,通过COPY requirement FROM STDIN WITH (FORMAT csv, DELIMITER '|')导入,性能比多行INSERT提升数倍。
  • 调整批次大小:根据服务器内存和数据库负载,测试不同批次大小(如2000、5000),找到最优值。
  • 事务批量提交:在批量插入前执行BEGIN,所有批次完成后执行COMMIT,减少事务提交的开销。
  • 连接池复用:如果有后续数据库操作,改用连接池(pg.Pool)代替单连接,提升连接利用率。

内容的提问来源于stack exchange,提问作者piyushCodes6

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 21:55:26