是否有人注意到EF Core 1.0 2015.1使查询效率低下

时间:2016-08-26 05:03:51

标签: 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);

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

因此生成的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

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

这在最新版本中有所改变,因为它曾用于RC版本的EF

我曾经遇到过的另一个问题是以下

         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();

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

1 个答案:

答案 0 :(得分:6)

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

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

enter image description here

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

我想做的另一个建议。那就是使用.AsNoTracking()尝试您的查询。这也会提高查询效果。

.AsNoTracking()

  

有时您可能希望从查询中获取实体但不具备   这些实体由上下文跟踪。这可能会带来更好的结果   以只读方式查询大量实体时的性能   场景。