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

标签 sql performance entity-framework asp.net-core-1.0

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

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

我们最终不得不将许多查询重写为存储过程以恢复性能。请注意,这些在 2015.1 版本之前曾经是高效的。显然有些事情发生了变化,许多查询正在选择表上的所有查询,然后在代码中过滤数据。这种方法对性能来说很糟糕,例如读取一个有很多行的表,过滤除两行之外的所有内容。

我必须问发生了什么变化,以及是否其他人也看到了同样的事情?

例如:我有一个 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

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

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

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

最佳答案

这是 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()

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.

关于sql - 有没有人注意到 EF Core 1.0 2015.1 使查询效率非常低,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39158596/

相关文章:

c# - 如何通过参数化查询在数据库中插入空值

mysql - 对维度进行分组的 SQL 场景

sql - 解释一下mysql中 "explain"查询的结果

entity-framework - 没有公钥的 EF 实体

sql - 检测帖子评级系统的滥用

java - 将实体作为方法参数传递与发送从实体的一部分创建的新对象

java - 就性能而言,: foo. setVisibility(View.GONE) 和parent.removeView(foo) 哪个更好?

c# - MVC4 最佳实践数据库模型 v View 模型(传递给 View )

c# - 在 Linq 中使用函数

mysql - 考勤 : Get time_in and time_out of flexible schedule Employees