2010-11-19 77 views
2

我们开始使用存储过程将具有实体框架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本身的速度确实更快!)

+0

我怀疑你的解决方案越抽象,生成SQL越难理解,因为需要覆盖更多的东西。即使这样你可能会发现SQL解析器很好地优化了它。 – Lazarus 2010-11-19 16:05:21

+0

问题是,我使用完全相同的LINQ查询并将其与LINQPad中的LINQ to Entites和LINQ to SQL提供程序进行对比,然后比较生成的SQL。或者,也许我不明白你的意见:) – Simon 2010-11-19 16:18:07

+0

你的第一个例子(while循环)的结果是错误标记的?从这个例子中可以看出,LINQ to Entities速度更快,似乎并不支持该帖子的其他内容。 – 2010-11-19 22:27:25

回答

2

当你说你实际上并不打算对性能进行基准测试。

仅仅因为SQL看起来不好,这并不意味着它执行非常糟糕(所有的时间)。

当使用实体框架或LINQ to SQL时,我真的不在乎生成的语句是什么样子,只要我的应用程序仍然符合我的标准。只有性能下降超过可接受的水平时,我才会麻烦微调查询以获得更好的SQL。

+0

有效点,我会做一些基准测试并回报。我的假设是,它会变慢,因为L2E查询长3倍,嵌套SELECT语句多3倍,所以也许SQL服务器本身在这里做一些优化?谁知道,我会去做基准测试。 – Simon 2010-11-19 16:15:53