【发布时间】:2021-05-23 12:55:31
【问题描述】:
我正在使用
queryRunner.manager.create(…)
在调用 save 方法之前创建实体。
我注意到,对于拥有大量数据的特定客户,创建步骤耗时 > 2 秒。 当我用自己创建新实体替换创建时
const myEntity = new MyEntity();
它使储蓄变得更快。
创建需要这么多时间的任何原因?会不会和这个实体的关系有关?
【问题讨论】:
我正在使用
queryRunner.manager.create(…)
在调用 save 方法之前创建实体。
我注意到,对于拥有大量数据的特定客户,创建步骤耗时 > 2 秒。 当我用自己创建新实体替换创建时
const myEntity = new MyEntity();
它使储蓄变得更快。
创建需要这么多时间的任何原因?会不会和这个实体的关系有关?
【问题讨论】:
问题是由于 TypeOrm 在 create() 方法中转换关系实例的方式, 似乎 typeOrm 正在对 create 中的每个给定实体和每个相关实体运行转换(如果您在 create() 方法中发送完整的关系实例及其关系)。
在进行任何修复之前,我对 create() 的调用如下所示:
const transaction = queryRunner.manager.create(Transaction, {
seller: sellerInstance,
buyer: buyerInstance
});
解决方案 1:仅发送 id — 如果您仍想使用 create(),请确保不要在创建字段中发送完整的关系实例,仅发送 id。 (此字段是您真正需要的唯一内容,因为这是表中的真正参考)。
const transaction = queryRunner.manager.create(Transaction, {
seller: { id: sellerInstance.id },
buyer: { id: buyerInstance.id },
});
解决方案 2:您始终可以使用 new()
const transaction = new Transaction();
transaction.seller = sellerInstance;
transaction.buyer = buyerInstance;
查看我的博客文章以了解有关此问题的更多详细信息:
https://tamar-duchovny.medium.com/two-lines-change-turned-a-6-sec-request-to-300ms-cf0f13c00a75
【讨论】:
在使用对其他实体的引用时,repository.create() 也有问题。我有一个复杂的操作,在事务中它会创建几个新实体并在其他新创建的实体中引用它们。问题变得如此严重,以至于整个应用程序都出现了响应问题,因为 NodeJS 事件循环被 Typeorm 的所有合并操作阻塞。
似乎 Typeorm 对实体引用的对象实例做了一些事情,它递归地通过它们或类似的东西。
我通过做两件事解决了这个问题:像你一样用新实体替换 create() 并用 insert 替换 save。 原文:
let entity = man.create(Entity, {
prop1: "something",
prop2: 42,
ref1: someOtherEntityInstance
};
entity = await man.save(Entity, entity); // set ID of new created entity
// ...
let anotherEntity = man.create(AnotherEntity, {
ref2: entity,
prop3: true,
};
anotherEntity = await man.save(Entity, entity);
适合我的版本
const entity = new Entity();
entity.prop1 = "something";
entity.prop2 = 42;
entity.ref1 = new SomeOtherEntity();
entity.ref1.id = someOtherEntityInstance.id;
let insertInfo = await man.insert(Entity, entity);
entity.id = (insertInfo.identifiers[0] as { id: number }).id;
const anotherEntity = new AnotherEntity();
anotherEntity.prop3 = true;
anotherEntity.ref2 = new Entity();
anotherEntity.ref2.id = entity.id;
insertInfo = await man.insert(Entity, entity);
anotherEntity.id = (insertInfo.identifiers[0] as { id: number }).id;
使代码更难看,但现在运行没有任何问题。
【讨论】: