我们开始使用存储过程将具有实体框架4的项目从VS2008迁移到VS2010作为ORM。与LINQ to SQL生成的SQL相比,LINQ to Entities生成的SQL效率低下吗?
现在我不得不做一个相当复杂的LINQ查询来从我们的数据库中获取数据。我通常首先尝试找出使用LINQPad的LINQ查询(伟大的工具btw!)。
现在我已经注意到,与LINQ to SQL相比,LINQ to Entities生成的SQL是可怕的,它生成的SQL语句与我们以前用存储过程类似。 L2E查询有很多嵌套的SELECT和INNER JOINS,只是看着它而伤了我的头!
这让我很好奇,我选择了另一个相当复杂的LINQ查询,并将LINQ to Entites生成的SQL与LINQ to SQL生成的SQL进行了比较。结果是类似的,L2E SQL非常糟糕,而且可能非常低效(我没有对它进行基准测试,但对于我来说,通过查看SQL语句很明显)
对不起,我不能给一些示例查询目前,但如果兴趣足够高,我可以建立一个虚拟数据库,并创建类似于我们使用的查询(混淆我们的查询和表将使查询无法读取和毫无意义)
那么什么您是否使用实体框架?没有人注意到糟糕的SQL语句,或者大多数人不关心吗?我是否错过了我应该知道的有关L2E的基本知识?
现在我非常遗憾,我们确实选择了使用LINQ to SQL的实体框架。
编辑:
所以我做了一些基准和WOW,我很惊讶!我将生成的SQL语句放入SQL Server Management Studio中的查询窗口中,并多次执行每个查询。以下是在WHILE循环中执行查询的平均结果1,10和100次。
1 time: LINQ to SQL: 440ms LINQ to Entities: 240ms 10 times: LINQ to SQL: 2900ms LINQ to Entities: 910ms 100 times: LINQ to SQL: 31600ms LINQ to Entities: 7000ms
我真的很惊讶!
我的下一个测试是创建一个简单的C#程序来生成和执行SQL语句。为了方便,我使用了LINQpad。对于每次测试,我都使用LINQPad中的LINQ to SQL和LINQ to Entities数据提供程序。查询每次完全一样。 测试程序是这样的:
void Main()
{
var sw = new Stopwatch();
for(int i = 0; i < 5; i++)
{
sw.Start();
for(int y = 0; y < 10; y++)
{
ExecuteQuery();
}
sw.Stop();
Console.WriteLine(string.Format("Pass {0}: {1}", i, sw.ElapsedMilliseconds));
sw.Reset();
}
}
private void ExecuteQuery()
{
//here is my 'complex' linq query
var dummy = (from p in....).ToList();
}
这一次,我有点失望,结果如下:
LINQ to SQL: Run 0: 805 Run 1: 726 Run 2: 722 Run 3: 717 Run 4: 767 LINQ to Entities: Run 0: 3031 Run 1: 3231 Run 2: 3085 Run 3: 3127 Run 4: 3148
我想不同的是由于SQL语句生成?还是我基准测试完全错了?建议?我已经在我们的项目中实现了LINQ查询(忘记提及该项目是一个ASP.NET MVC 3 RC Web应用程序)。我们基本上是用自定义的网格显示一个页面。使用LINQ to Entities加载网格数据大约需要300-400ms!使用LINQ to SQL加载数据需要大约70-80ms。这实际上与我在上面的LINQPad中的测试应用中的结果非常相似。
我一直在寻找EF过去几个小时的性能问题,并且发现了很多初始查询的问题。事实上,最初的查询速度较慢,但只有大约200毫秒,所以第一个查询需要大约600毫秒,而其他后续查询需要300-400毫秒。我也读了precompiling views with EdmGen,但没有什么区别。我发现另一个blog post that compared LINQ to SQL performance with EF,结果似乎是相似的,虽然这是EF 3.5。然后我发现blog post about EF with heavy inheritance,但这不适用于我的情况。
除了上百个“初始查询很慢”类型的帖子,我没有发现任何与我的问题有关的东西。我的意思是,与Linq to SQL相比,我并不介意性能受到影响,但70ms与300ms的差别是巨大的!它确实会影响我们网络应用程序的用户体验。
我要尝试的最后一件事是预编译查询。如果性能没有得到改善,那么我可以切换到LINQ to SQL(尽管生成的SQL本身的速度确实更快!)
我怀疑你的解决方案越抽象,生成SQL越难理解,因为需要覆盖更多的东西。即使这样你可能会发现SQL解析器很好地优化了它。 – Lazarus 2010-11-19 16:05:21
问题是,我使用完全相同的LINQ查询并将其与LINQPad中的LINQ to Entites和LINQ to SQL提供程序进行对比,然后比较生成的SQL。或者,也许我不明白你的意见:) – Simon 2010-11-19 16:18:07
你的第一个例子(while循环)的结果是错误标记的?从这个例子中可以看出,LINQ to Entities速度更快,似乎并不支持该帖子的其他内容。 – 2010-11-19 22:27:25