我们开始将项目从带有存储过程的VS2008迁移到VS2010,实体框架4作为ORM。
现在我不得不做一个相当复杂的LINQ查询来从我们的数据库中获取数据。我通常首先尝试使用LINQPad找出LINQ查询(很棒的工具顺便说一句!)。
现在我注意到,与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语句生成造成的?或者我完全错误的基准测试?建议?
EDIT2: 我在我们的项目中实现了LINQ查询(忘了提到该项目是一个ASP.NET MVC 3 RC Web应用程序)。我们基本上显示一个带有自定义网格的页面。使用LINQ to Entities加载网格数据大约需要300-400毫秒!使用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本身确实更快!)
答案 0 :(得分:2)
当你说你实际上并没有费心去衡量表现时,你就失去了我。
仅仅因为SQL看起来很糟糕,这并不意味着它的表现非常糟糕(始终如此)。
当使用Entity Framework或LINQ to SQL时,只要我的应用程序仍符合我的标准,我真的不在乎生成的语句是什么样的。只有在性能降低到可接受的水平之后,我才会对查询进行微调以获得更好的SQL。