Entity Framework 性能下降

5

我有一个非常简单的edmx模型,只有一个数据库和一个实体对应一个数据库表。测试从本地虚拟数据库服务器中按顺序检索所有记录。

using System;
using System.Linq;

namespace ConsoleApplication1
{
    using System.Diagnostics;

    private static readonly ConcurrentBag<long> Stats = new ConcurrentBag<long>();
    static void Main(string[] args)
    {
        for (int i = 0; i < 5; i++)
        {
            var sw = Stopwatch.StartNew();
            using (var ctx = new ScratchEntities())
            {
                foreach (var invoice in ctx.Invoices.Select(
                    s => new
                         {
                             s.Id,
                             s.Amount,
                             s.DueDate
                         }))
                {

                }
            }
            sw.Stop();
            Stats.Add(sw.ElapsedMilliseconds);
        }
        Console.WriteLine("Min {0}    Max {1}    Avg {2}", Stats.Min(), Stats.Max(), Stats.Average());

    }
}

在EF 4和5下,执行需要约2-2.5秒。升级到Nuget的EF6后,需要近10秒。 类似地,使用foreach遍历ctx.Invoices时需要的时间大约是遍历ctx.Invoices.Select(s=>new{all columns here})的4-5倍。 感到困惑。 更新: 迭代5次 EF 6.0.1最小值3082,最大值9231,平均值4462.8 EF 5.0.0最小值1502,最大值2016,平均值1665.4 所有时间都是1M行的毫秒数。 .Net 4.5 更新2: 在105个测试中排除前五个测试 EF 6.0.1最小值2698,最大值4383,平均值3136 EF 5.0.0最小值1426,最大值2922,平均值1628 更新3: 按照这里的建议重新创建TT模板后 EF 6.0.1最小值2589,最大值4279,平均值3027 按照这里所述编译EF6后 EF 6.0.1最小值2644,最大值4322,平均值3045.7 更新4: 更改为AsEnumerable后 EF 6.0.1最小值2661,最大值4658,平均值3134.6

1
在同一个应用程序域/进程中对其进行两次基准测试。第一次创建上下文时,需要进行大量的清理工作。 - ta.speot.is
2
我在微软EF团队工作。有几件事情需要检查。 您是否使用调试器运行?如果是这样,我们正在努力修复一个已知问题 - http://entityframework.codeplex.com/workitem/1778。 您能否确认您拥有NuGet包的6.0.1版本。在6.0.0中存在一些其他性能问题,我们在6.0.1补丁发布中进行了修复。 如果以上两种情况都不是,请提供EDMX文件的副本,以便我们找出导致性能缓慢的原因。 - Rowan Miller
@RowanMiller 我看到了你的文章,来这里发布它。但是你已经做到了。感谢你在 EF 上的所有工作。 - ta.speot.is
嗨,Darek。你的数据库中有多少张发票?如果你已经提供了这个信息而我没有注意到,那我很抱歉。 - divega
有一百万张发票。实体不需要被跟踪。但是这篇文章并不是关于EF性能的总体情况,而只是关于EF 6中的退化问题。 - Darek
显示剩余7条评论
1个回答

3

在EF6中,我们将默认的数据检索行为从流式处理更改为缓冲式处理(请参见这里,了解原因)。缓冲会增加额外的开销,特别是在执行无跟踪查询时,比如投影到未映射的CLR类型或通过AsNoTracking扩展方法。为了缓解这个问题,我们添加了AsStreaming扩展方法,可以在每个查询上关闭缓冲。使用AsStreaming应该会给您带来类似EF5的性能。


1
AsStreaming现已被弃用。我认为在EF6中,性能已经回到了没有AsStreaming的EF5水平。 - nawfal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接