В нашей системе мы столкнулись с проблемами производительности при использовании QueryFilters в ядре EF.
Проблема заключается в том, что ядро 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);
В настоящее время в каждой таблице имеется следующее количество записей:
- Покупка предложения метаданных: 12'654'639
- Предложение о покупке: 1'689'634
Кто-нибудь также сталкивался с этой проблемой и мог бы найти решение этой проблемы?