使用TypeORM实现PostgreSQL批量插入/更新的问题求助
TypeORM实现PostgreSQL批量插入/更新(含大数据量场景)
问题重现
你定义了Test实体:
export class Test { @PrimaryColumn('integer') id: number; @Column('varchar', { length: 255 }) testName: string; }
尝试批量插入数据时(注意原代码存在笔误:script.id = 1应为test1.id = 1):
const test1 = new Test(); test1.id = 1; test1.testName = 't1'; const test2 = new Test(); test2.id = 2; test2.testName = 't2'; const test3 = new Test(); test3.id = 3; test3.testName = 't3'; const tests = [test1, test2, test3];
执行await testRepository.save(tests)失败,但单独调用testRepository.save(test1)正常运行,需要解决批量插入/更新,尤其是数千行数据的场景。
解决方案
1. 先修正代码笔误
原测试代码里的script.id = 1是笔误,应该改为test1.id = 1,这个错误会导致test1的主键未赋值,批量save时触发主键缺失报错。修正后小数据量场景下repository.save()本身支持批量操作。
2. 纯批量插入(仅新增数据)
如果不需要处理主键冲突,直接用insert方法,它会生成单条INSERT语句,性能比save更高:
// 无需创建实体实例,直接构造数据数组更高效 const testsData = [ { id: 1, testName: 't1' }, { id: 2, testName: 't2' }, { id: 3, testName: 't3' } ]; await testRepository.insert(testsData);
3. 批量插入/更新(Upsert:存在则更新,不存在则插入)
如果需要处理主键冲突,PostgreSQL支持ON CONFLICT语法,推荐用QueryBuilder实现,性能最优:
const testsData = [ { id: 1, testName: 't1_updated' }, // 已存在,会更新testName { id: 2, testName: 't2' }, { id: 4, testName: 't4_new' } // 不存在,会插入 ]; await testRepository .createQueryBuilder() .insert() .into(Test) .values(testsData) .onConflict(`("id") DO UPDATE SET "testName" = EXCLUDED."testName"`) .execute();
onConflict("id")指定冲突的主键字段EXCLUDED指代插入时的新数据,用来覆盖已有记录的字段
4. 大数据量分批处理
当数据量达到数千甚至上万条时,一次性插入可能超时或影响数据库性能,建议分批插入:
const batchSize = 500; // 根据数据库性能调整每批大小 const testsData = [...你的数千条数据]; for (let i = 0; i < testsData.length; i += batchSize) { const batch = testsData.slice(i, i + batchSize); // 纯插入用insert await testRepository.insert(batch); // 或Upsert用QueryBuilder // await testRepository.createQueryBuilder().insert().into(Test).values(batch).onConflict(...).execute(); }
内容的提问来源于stack exchange,提问作者Anurag A S
相关产品推荐
相关产品推荐

