簡體   English   中英

EF核心QueryFilter的性能問題

[英]Performance problems with EF core QueryFilter

在我們的系統中,我們在EF核心中使用QueryFilters時遇到了性能問題。 問題是EF核心在LEFT JOIN內部過濾而不是在其外部進行過濾。

生成的SQL看起來像這樣:

SELECT [pom].[Id],
        [pom].[DeleteDate],
        [pom].[UpdateDate],
        [pom].[Version],
        [t].[Id],
        [t].[MandatorId],
        [t].[NetPriceAmount],
        [t].[NetPriceCurrencyIso4217Code]
FROM [externaldata].[PurchaseOfferMetadata] AS [pom]
    LEFT JOIN (
    SELECT [po].[Id],
            [po].[MandatorId],
            [po].[NetPriceAmount],
            [po].[NetPriceCurrencyIso4217Code]
    FROM [externaldata].[PurchaseOffer] AS [po]
    WHERE [po].[MandatorId] = 1
) AS [t] ON [pom].[Id] = [t].[Id]
WHERE [pom].[Id] IN 
    (CAST(3094411 AS bigint), 
    CAST(4757070 AS bigint), 
    CAST(4757112 AS bigint), 
    CAST(5571232 AS bigint))

有問題的部分是WHERE [po].[MandatorId] = 1 如果這將在第二個WHERE語句中,則查詢運行得更快。

數據庫模型配置如下:

modelBuilder.Entity<PurchaseOffer>()
      .HasQueryFilter(po => po.MandatorId == 1)
      .ToTable(nameof(PurchaseOffer), schema: ExternalDataSchemaName);

modelBuilder.Entity<PurchaseOfferMetadata>()
      .HasOne(pom => pom.PurchaseOffer)
      .WithOne(po => po.Metadata)
      .HasForeignKey<PurchaseOffer>(po => po.Id);

在數據庫上我們設置了這樣的外鍵:

IF OBJECT_ID('[externaldata].[FK_PurchaseOffer_PurchaseOfferMetadata]', 'F') IS NULL
BEGIN
    ALTER TABLE [externaldata].[PurchaseOffer] ADD CONSTRAINT [FK_PurchaseOffer_PurchaseOfferMetadata] FOREIGN KEY
    (
        [Id]
    )
    REFERENCES [externaldata].[PurchaseOfferMetadata] ([Id])
END;

EF核心查詢如下所示:

var existingPurchaseOfferMetadatasById = await db.PurchaseOfferMetadatas
   .Where(pom => purchaseOfferIds.Contains(pom.Id))
   .Include(pom => pom.PurchaseOffer)
   .ToDictionaryAsync(pom => pom.Id, cancellationToken);

目前,我們在每個表中都有以下數量的記錄:

  • PurchaseOfferMetadata:12'654'639
  • PurchaseOffer:1'689'634

有沒有人也遇到過這個問題,可能會找到解決方案嗎?

在連接很復雜時,EF在創建最優化的SQL查詢方面一直沒有做得很好。 我無法回答你如何讓Linq了解你的數據庫優化設計; 但是,如果您知道應該生成的SQL,那么我建議為了更好的復雜READ性能,使用像Dapper這樣的NuGet包來編寫您想要的確切SQL並獲得數據庫應該得到的連接。

using Dapper;

[...]

public class SalsaZima
{
  public int ID { get; set; }
  public string MySalsaColumn { get; set; }
  public string MyZimaColumn { get; set; }
}

[...]

// get data from database
using (IDbConnection dp = Dapper)
{
  string query = @"SELECT 
                     s.ID
                    ,s.MySalsaColumn
                    ,z.MyZimaColumn
                   FROM dbo.Salsa s 
                   LEFT JOIN dbo.Zima z
                     ON s.ZimaID = z.ID";

  return dp.Query<SalsaZima>(query).ToList();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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