有没有人注意到 EF Core 1.0 2015.1 使查询效率非常低

Has anyone noticed that EF Core 1.0 2015.1 has made the queries very inefficient

升级到 Asp.Net Core 2015.1 后,我注意到很多 EF 查询变得比 运行 慢很多。

我做了一些调查,发现很多带有 where 过滤器的查询现在在代码中进行评估,而不是将过滤器作为 where 子句的一部分传递给 SQL 运行与查询。

我们最终不得不将一些查询重写为存储过程以恢复性能。请注意,这些在 2015.1 版本之前是有效的。显然有些东西发生了变化,很多查询都在 select 上对 table 进行所有查询,然后在代码中过滤数据。这种方法对性能很糟糕,例如读取包含很多行的 table 以过滤除 2 行以外的所有内容。

我想问一下发生了什么变化,是否有其他人看到同样的事情?

例如:我有一个 ForeignExchange table 和一个 ForeignExchangeRate table 通过 ForeignExchangeid = ForeignExchangeRate.ForeignExchangeId

链接
await _context.ForeignExchanges
                .Include(x => x.ForeignExchangeRates)
                .Select(x => new ForeignExchangeViewModel
                {
                    Id = x.Id,
                    Code = x.Code,
                    Name = x.Name,
                    Symbol = x.Symbol,
                    CountryId = x.CountryId,
                    CurrentExchangeRate = x.ForeignExchangeRates
                        .FirstOrDefault(y => (DateTime.Today >= y.ValidFrom) 
                                          && (y.ValidTo == null || y.ValidTo >= DateTime.Today)).ExchangeRate.ToFxRate(),
                    HistoricalExchangeRates = x.ForeignExchangeRates
                        .OrderByDescending(y => y.ValidFrom)
                        .Select(y => new FxRate
                        {
                            ValidFrom = y.ValidFrom,
                            ValidTo = y.ValidTo,
                            ExchangeRate = y.ExchangeRate.ToFxRate(),
                        }).ToList()

                })
                .FirstOrDefaultAsync(x => x.Id == id);

我用它来获取编辑外汇汇率的数据

所以生成的SQL不是预期的。它生成以下 2 SQL 语句来获取数据

SELECT TOP(1) [x].[ForeignExchangeId], [x].[ForeignCurrencyCode], [x].[CurrencyName], [x].[CurrencySymbol], [x].[CountryId], (
SELECT TOP(1) [y].[ExchangeRate]
FROM [ForeignExchangeRate] AS [y]
WHERE ((@__Today_0 >= [y].[ValidFrom]) AND ([y].[ValidTo] IS NULL OR ([y].    [ValidTo] >= @__Today_1))) AND ([x].[ForeignExchangeId] = [y].[ForeignExchangeId])
)FROM [ForeignExchange] AS [x]
WHERE [x].[ForeignExchangeId] = @__id_2

SELECT [y0].[ForeignExchangeId], [y0].[ValidFrom], [y0].[ValidTo], [y0].[ExchangeRate]
FROM [ForeignExchangeRate] AS [y0]
ORDER BY [y0].[ValidFrom] DESC

第二个查询导致速度缓慢。如果 table 有很多行,那么它基本上获取整个 table 并在代码

中过滤数据

这在最新版本中已更改,因为它曾经在 EF 的 RC 版本中工作

我曾经有过的另一个查询如下

         return await _context.CatchPlans
            .Where(x => x.FishReceiverId == fishReceiverId
                     && x.FisherId == fisherId
                     && x.StockId == stockId
                     && x.SeasonStartDate == seasonStartDate
                     && x.EffectiveDate >= asAtDate
                     && x.BudgetType < BudgetType.NonQuotaed)
            .OrderBy(x => x.Priority)
            .ThenBy(x => x.BudgetType)
            .ToListAsync();

并且此查询最终进行了 Table 读取(整个 table 有数万行)以获取 2 到 10 条记录的过滤子集。非常低效。这是我必须用存储过程替换的一个查询。从大约 1.5-3.0 秒减少到毫秒。并注意这在升级

之前用于 运行

这是 EF core 1.0 上的一个已知问题。现在的解决方案是将所有关键查询转换为 sync one.The 问题出在 Async 查询上 now.They会在EF core 1.1.0上解决这个问题version.But它还没有发布。

这是 EF 核心开发团队成员完成的测试:

您可以在这里找到更多信息:EF Core 1.0 RC2: async queries so much slower than sync

我想 do.That 的另一个建议是尝试使用 .AsNoTracking() 进行查询。这也将提高查询性能。

.AsNoTracking()

Sometimes you may want to get entities back from a query but not have those entities be tracked by the context. This may result in better performance when querying for large numbers of entities in read-only scenarios.