【问题标题】:typeorm efficient bulk updatetypeorm 高效批量更新
【发布时间】:2021-01-24 16:36:38
【问题描述】:

我有一个在postgresql 数据库上使用typeorm 的更新查询,如下所示,它经常对20 多个项目的列表执行(每30 秒一次)。大约需要。更新需要 12 秒,这对于我的极限来说已经很长了。

for (item of items) {
    await getConnection().createQueryBuilder().update(ItemEntity)
        .set({status: item.status, data: item.data})
        .whereInIds(item.id).execute();
}

是否可以在单个查询中执行这样的批量更新,而不是迭代其他项目?如果是这样 - 如何?

item.statusitem.data 对于每个项目都是唯一的。

【问题讨论】:

  • 当我遇到相同的行为时,我构建了一个常规 SQL 查询,通过一个查询更新所有项目,然后执行它。我相信这是最高效的方式。

标签: javascript postgresql orm typeorm


【解决方案1】:

使用纯 psql 可以按照以下答案中的描述完成:Update multiple rows in same query using PostgreSQL

但是,来自 Typeorm 的 UpdateQueryBuilder 不支持 from 子句。 目前,我认为原始查询是唯一的方法,即getManager().query("raw sql ...")

【讨论】:

  • 是的,用原始查询做到了
  • 嗨,你能分享一下你是怎么做到的吗?我仍在努力将值放入查询中。
  • @ZarghamKhan 这是一种方法。 Entitymanager 调用存储函数。 await entityManager.query(`SELECT public.f_transact(array[${str}]::public.type_transaction[])`); f_transact 是一个存储函数。 str 是一个值数组,例如('${v1}','${v2}','${v3}'); type_transaction 是我的数据库中定义的类型。 数据的验证在应用程序代码中完成。
【解决方案2】:

有一种方法可以通过 upsert 解决此问题

使用数据库中已经存在的数据数组并使用 ON CONFLICT 对其进行更新。

const queryInsert = manager
    .createQueryBuilder()
    .insert()
    .into(Entity)
    .values(updatedEntities)
    .orUpdate(["column1", "column2", "otherEntityId"], "PK_table_entity")
    .execute();

将运行类似:

INSERT INTO entity (
    "id", "column1", "column2", "otherEntityId"
) VALUES 
    ($1, $2, $3, $4), 
    ($5, $6, $7, $8), 
ON CONFLICT 
    ON CONSTRAINT "PK_table_entity" 
    DO UPDATE SET 
        "column1" = EXCLUDED."column1", 
        "column2" = EXCLUDED."column2", 
        "otherEntityId" = EXCLUDED."otherEntityId"

但您需要注意 orUpdate 不支持使用实体关系,您需要传递关系实体的 id 列。它也不会对命名策略进行任何操作。另一个问题是它只有在你的 pk 不使用 @PrimaryGeneratedColumn 时才有效(你可以使用 @PrimaryColumn 代替)

【讨论】:

    猜你喜欢
    • 2011-01-18
    • 2021-02-19
    • 2016-08-15
    • 1970-01-01
    • 2016-01-13
    • 1970-01-01
    • 1970-01-01
    • 2011-06-19
    • 1970-01-01
    相关资源
    最近更新 更多