针对SQL等效的LINQ查询的性能

时间:2011-07-06 15:00:29

标签: .net sql linq performance

我目前正在与正在工作的人讨论针对SQL等效的LINQ查询的性能。

有没有人对此进行过任何科学测试?

如果没有,出于性能原因,你必须用SQL查询替换LINQ的轶事证据将有助于我说明问题。

8 个答案:

答案 0 :(得分:9)

我对此略有不同;在进行性能分析时(使用我们的shiny profiler),我们注意到LINQ(在本例中为SQL)正在为基本查询生成TSQL,并且操作在DB服务器上运行得非常快(0.5ms等) - 但是,实际的查询操作花费的时间更长(对于相同的0.5ms查询,在某些情况下为20ms +)。那么时间到了哪儿?您可能会想到“查询翻译”,但没有;我们还有很多ExecuteQuery<T>代码(即你手工编写TSQL的地方),这就是 完全相同的东西 。事实证明, materializer 身份地图之间的某个地方正在丢失大量时间。

因此;我们编写了自己的物化器,它是ExecuteQuery的替代品,因而诞生了dapper

在更多LINQ方面,它通常可以为简单查询生成TSQL,但对于任何复杂的东西,我通常都信任手工编码的TSQL。以案例为样本,我有一个涉及组,跳过和接受的复杂查询。它表现不佳。当我用ROW_NUMBER()等手写它时,相同的结果占据了“统计IO”和总时间的4%。

我目前对LINQ的看法是,ORM工具使数据变异变得轻而易举,但对于 查询 ,我倾向于使用 hardy中。这是具有讽刺意味的,因为LINQ中的Q是“查询”。

答案 1 :(得分:6)

LINQ2SQL或者LIN中的LINQ需要有一个关于如何将LINQ查询转换为SQL的通用规则集,并引入了抽象概念。这种抽象有时会导致语句不是最优的。手动编写SQL语句可以根据具体情况进行调整 这导致得出结论,SQL的速度更快,特别是在复杂场景中。但这并不意味着每个LINQ查询都比它的SQL等价慢 我将EF 1与Oracle结合使用的经验支持了这一点。

答案 2 :(得分:4)

SQL查询更好的一个更明显的例子是更新/删除批处理。 LINQ-To-SQL中没有内置工具来处理多个更新或删除,除了逐个处理记录,这会为每条记录生成单独的查询。

var myRecords = myContext.Books.Where(b => b.Author = "Bob");
foreach (var rec in myRecords)
    myContext.Books.DeleteOnSubmit(rec);
myContext.SubmitChanges()  // generates delete statement for each record.

在一般情况下,LINQ经过优化可以生成非常高效的查询,并且有时可以生成比使用SQL编写查询的直观方式更好的查询。但是,总会有例外情况,LINQ-to-SQL语句的效率不如可以手工编写的SQL查询。

答案 3 :(得分:2)

LinqToSql是ADO.Net之上的一个层。因此,如果您将ADO.Net与Sql查询一起使用,您将比LinqToSql“更快”(通过不做LinqToSql所做的额外事情)。

可以对.Net和机器代码进行同样的论证(当性能是唯一的标准时)。 .Net IL最终是JIT的机器,如果你刚开始写机器,你会更快。

以下是几个重要的场景:

  • 如果您的查询是低IO并且返回了大量数据以实现实现,则LinqToSql将比原始sql花费更多时间。另一方面,您最终使用的是Customer实例而不是DataRows。
  • 如果您的查询是高度动态的,那么您永远不会发出两次相同的SQL文本,那么您将始终产生查询转换成本。 Sql查询会更快(特别是如果你不计算sql文本的构造)。

以下几种情况无关紧要:

  • 如果您的查询数据库IO很重(报表样式),您将不会注意到LinqToSql抽象的额外客户端CPU成本。
  • 如果您的查询是重复的(具有不同参数的相同查询),可以通过使用CompiledQuery来减轻LinqToSql抽象的大部分成本。 &lt; - 我认为大多数系统都符合这种情况。

答案 4 :(得分:0)

当您运行LINQ查询时,LINQ会生成T-SQL代码以执行查询。您可以运行SQL Server Profiler以了解查询的外观。我在过去做过,生成的T-SQL看起来很干净。

我不能直接谈论性能,因为我没有运行任何数字,但我看到的一件事是,除非你在表中使用rowversion列进行LINQ查询,否则你最终会得到每一列在WHERE子句中包含的表中,这是作为LINQ的内置乐观并发检查的一部分完成的。使用rowversion列允许LINQ仅使用该列进行此检查,并使T-SQL更清晰,性能更高。

答案 5 :(得分:0)

请检查其他问题:LINQ-to-SQL vs stored procedures?

在我看来,linq几乎可以用于所有方面。对于一些罕见的情况,当你非常擅长sql并且真的想要提高性能时,请转而使用原始sql。

答案 6 :(得分:0)

今年早些时候,我在单个交易集中插入了许多记录时,提交了一份针对Linq2Sql性能的错误报告。由于Linq2Sql必须检查数据库服务器要检查的关系,因此每个插入的处理时间越来越长,因此需要处理。

您可以在https://connect.microsoft.com/VisualStudio/feedback/details/637841/linq-to-sql-shows-progressively-worse-performance-as-the-transaction-set-grows

查看错误报告

点击显示详细信息,我添加了一些性能数据。

有趣的是,微软的答案是他们没有计划提高Linq2Sql的性能,而且我应该使用ADO.Net这是我已经决定做的事情。

此时我的底线是我喜欢Linq2Sql查询,但不会将其用于插入或更新。我也喜欢Linq2Sql将为我填充外键中的记录,而无需编写单独的查询。

对于复杂的查询 - 我大约50%使用Linq2Sql和大约50%的存储过程。 我从不做内联SQL,因为我更喜欢使用强类型的方法。因此,对于简单的查询,Linq2Sql的简单性在100%的时间内胜过ADO.Net。

答案 7 :(得分:-1)

通常,根据我的经验,EF4.1或LINQtoSQL的问题不是LINQ,而是编码器。

开发人员通常不知道如何编写有效的查询代码或如何编写高效且可伸缩的数据库访问(即他们熟悉VB或C#,但不知道SQL),这表明他们如何构建查询。那时,它们是否正在使用LINQ并不重要。

真正显示的是应用程序在开发中正常工作(dev数据库有几十万行数据),但在生产中表现不佳(数百万行数据)。开发人员立即指出它在开发中运行良好,因此它必须是数据库而不是代码的错误。这就是开发人员和DBA之间的战争。

虽然我非常喜欢LINQ,但您最好将查询移动到存储过程中,这样您就可以调整和调整数据访问,而无需在应用程序上为每个未成年人执行完整的Dev-Test-QA-Release周期更新