实体框架合并选项不跟踪不良性能
我有一个奇怪的行为,试图执行将 ObjectQuery MergeOption 声明为“NoTracking”的查询,在这种情况下,实体框架不应附加任何实体,也不应创建相对的 ObjectStateEntry 来跟踪实体状态。
问题是,性能不但没有提高,反而变得更糟,相同的查询使用默认合并选项(即 AppendingOnly)大约需要 10 秒,如果我尝试指定 notracking 则需要更多 1 分钟
有人对此有解释吗?
I have a strange behavior trying to execute a query declaring ObjectQuery MergeOption to "NoTracking", in this case entity framework should not attach any entity and not create the relative ObjectStateEntry to track entity state.
The problem is that instead of increase performance it get worse, the same query takes like 10 seconds with default mergeoption (that is AppendingOnly) and more the 1 minutes if I try to specify notracking
Does someone have an explanation for this??
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果通过设置
NoTracking
合并选项来禁用更改跟踪,则可以节省将对象附加到上下文的性能成本,但另一方面,您也会失去身份管理。这意味着可能会有更多的对象(许多具有相同的密钥)将被具体化。
示例:假设您有一个
User
实体,其中一个Roles
集合作为导航属性。另外,假设数据库中有 100 万个用户,并且所有用户都具有相同的 10 个角色,即每个用户都有一个包含 10 个元素的角色集合。如果您运行以下查询......具体化和实例化对象的数量取决于合并选项:
如果您不使用
NoTracking
,您将在其中拥有 1.000.010 个对象内存,即 100 万个用户,但只有 10 个角色,因为身份映射将确保每个键只有 1 个角色被具体化并附加到上下文。相同的 10 个角色实例用于所有用户的Roles
集合。但是,如果您使用
NoTracking
,EF 不会将对象附加到上下文,因此身份管理被禁用,内存中将有 11.000.000 个对象:每个对象有 100 万个用户和 10 个角色实例用户,即1000万个角色对象。因此,您拥有的物化对象数量是对象附加到上下文时的 10 倍以上。对象具体化被分类为“中等”性能成本:
换句话说:如果查询使用
NoTracking
合并选项,此阶段确实会影响性能 并且禁用更改跟踪的性能优势可能会被禁用身份管理和倍增对象物化的缺点所破坏。自 EF Core 5.0 起,有附加选项 'NoTrackingWithIdentityResolution'< /a> 禁用一般跟踪,但会进行身份解析。
If you disable change tracking by setting the
NoTracking
merge option you save the performance costs of attaching objects to the contexts but on the other hand you also lose identity management.This means that potentially much more objects - many with the same key - will be materialized.
Example: Suppose you have a
User
entity with aRoles
collection as navigation property. Also suppose you have 1 million users in the database and all users are in the same 10 roles, i.e. every user has a roles collection with 10 elements. If you run the following query......the number of materialized and instantiated objects depends on the merge option:
If you don't use
NoTracking
you will have 1.000.010 objects in memory, namely 1 million users, but only 10 roles because identity mapping will ensure that only 1 role per key is materialized and attached to the context. The same 10 role instances are used for all user'sRoles
collection.If you use
NoTracking
however, EF won't attach objects to the context, hence identity management is disabled and you will have 11.000.000 objects in memory: 1 million users and 10 role instances per user, i.e. 10 million role objects. So, you have more than 10 times as many materialized objects as when the objects are attached to the context.Object materialization is classified with "moderate" performance costs:
In other words: If the query uses the
NoTracking
merge option, this stage does affect performance and it might be possible that the performance benefits of disabled change tracking are destroyed by the drawbacks of disabled identity management and multiplied object materialization.Since EF Core 5.0 there is the additional option 'NoTrackingWithIdentityResolution' which disables general tracking but will do identity resolution.