簡體   English   中英

EF Core 查詢性能

[英]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 而是使用JoinSelect表達式加載您需要的最少數據量。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM