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

Gra*_*son 7 sql performance entity-framework asp.net-core-1.0

升级到Asp.Net Core 2015.1之后,我注意到很多EF查询运行起来都慢得多.

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

我们最终不得不重新编写一些查询作为存储过程来恢复性能.请注意,这些在2015.1发布之前一直很有效.显然有些东西被改变了,很多查询正在选择表上的所有查询,然后在代码中过滤数据.这种方法对于性能来说非常糟糕,例如读取包含大量行的表,过滤除了2行之外的所有内容.

我不得不问有什么改变,以及是否有其他人看到同样的事情?

例如:我有一张ForeignExchange桌子和一张ForeignExchangeRate桌子,通过这些桌子相连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);
Run Code Online (Sandbox Code Playgroud)

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

因此生成的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
Run Code Online (Sandbox Code Playgroud)

SELECT [y0].[ForeignExchangeId], [y0].[ValidFrom], [y0].[ValidTo], [y0].[ExchangeRate]
FROM [ForeignExchangeRate] AS [y0]
ORDER BY [y0].[ValidFrom] DESC
Run Code Online (Sandbox Code Playgroud)

第二个查询是导致缓慢的问题.如果表有很多行,那么它基本上获取整个表并在代码中过滤数据

这在最新版本中已经发生了变化,因为这曾经在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();
Run Code Online (Sandbox Code Playgroud)

并且此查询最终执行了一个表读取(整个表中有数万行),以获得2到10个记录之间的过滤器子集.非常低效.这是我必须用存储过程替换的一个查询.从大约1.5-3.0秒减少到毫秒.请注意,这在升级之前用于高效运行

Sam*_*ath 6

这是一个已知的问题EF core 1.0.现在的解决方案是将所有关键查询转换为一个sync.问题就在于Async查询EF core 1.1.0.他们会在版本上解决这个问题.但它尚未发布.

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

在此输入图像描述

您可以在此处找到更多信息:EF Core 1.0 RC2:异步查询比同步慢得多

我想做的另一个建议.那就是尝试你的查询.AsNoTracking().这也会提高查询性能.

.AsNoTracking()

有时您可能希望从查询中获取实体,但不会通过上下文跟踪这些实体.在只读方案中查询大量实体时,这可能会带来更好的性能.