[英]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.