[英]EF Core Query Performance
我有一个加载非常缓慢的查询。 我认为它有很大的问题,但我不明白为什么。 在我的应用程序中,我有一个实体 KeyText:
public class KeyText
int Id
Group Group
string Text
大多数其他实体有几个这样的关键文本。 它只是填充组合框的一种简单方法。 因此,如果我像这样通过 ef 核心加载:(ThenInclude lambda 中的所有内容都是 KeyText)
context.Companies
.Include(c => c.Adresses).ThenInclude(a => a.AdressType);
.Include(c => c.Adresses).ThenInclude(a => a.CityType);
.Include(c => c.Adresses).ThenInclude(a => a.AnotherKeyText);
.Include(c => c.Adresses).ThenInclude(a => a.DifferentKeyText);
在真正的应用程序中,这可以加载最多 20 秒的数据量。 我说的是 5 collections 中的 5 个条目。
但是,如果我这样加载:
var companies = context.Companies;
companies.adresses = context.Adresses
Include(a => a.AdressType)
Include(a => a.CityType)
Include(a => a.AnotherKeyText)
Include(a => a.DifferentKeyText);
它立即加载。 为什么是这样? 第一个查询错了吗?
假设您有 5 家公司,每家公司有 5 个地址:
context.Companies
.Include(c => c.Adresses).ThenInclude(a => a.AdressType);
.Include(c => c.Adresses).ThenInclude(a => a.CityType);
.Include(c => c.Adresses).ThenInclude(a => a.AnotherKeyText);
.Include(c => c.Adresses).ThenInclude(a => a.DifferentKeyText);
此代码生成 5*5=25 left join 代表 Sql 每一个由 3 个 join 组成(Companies * Adresses * types)
var companies = context.Companies;
companies.adresses = context.Adresses
.Include(a => a.AdressType)
.Include(a => a.CityType)
.Include(a => a.AnotherKeyText)
.Include(a => a.DifferentKeyText);
此代码生成 5 个左连接代表 Sql 每一个由 2 个连接(地址 * 类型)组成
所以很明显,第一种方法会显着损害你的表现。
无论如何尽量不要使用Include
。 而是使用Join
和Select
表达式加载您需要的最少数据量。
在EF中加快查询速度的另一个选项是使用.AsNoTracking()
var companies = context.Companies.AsNoTracking();
companies.adresses = context.Adresses.AsNoTracking()
.Include(a => a.AdressType)
.Include(a => a.CityType)
.Include(a => a.AnotherKeyText)
.Include(a => a.DifferentKeyText)
context.Companies.AsNoTracking()
.Include(c => c.Adresses).ThenInclude(a => a.AdressType);
.Include(c => c.Adresses).ThenInclude(a => a.CityType);
.Include(c => c.Adresses).ThenInclude(a => a.AnotherKeyText);
.Include(c => c.Adresses).ThenInclude(a => a.DifferentKeyText);
当结果用于只读方案时,没有跟踪查询很有用。 它们执行速度更快,因为无需设置更改跟踪信息。 如果您不需要更新从数据库中检索到的实体,则应使用无跟踪查询。 您可以将单个查询交换为不跟踪
默认情况下,返回实体类型的查询正在跟踪。 这意味着您可以对这些实体实例进行更改,并通过SaveChanges()
这些更改。
默认情况下,当您从数据库加载数据时, ChangeTracker
已跟踪所有记录,这将导致速度和 memory 分配略有下降。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.