当使用编译查询时,我们是否仍需要存储过程?

14
在使用编译查询执行Entity Framework(或Linq-to-SQL)与SQL Server相结合时,是否仍然有使用存储过程的性能优势?
编译查询将被缓存为参数化查询,因此性能应与存储过程接近。是否存在使用存储过程会显着更好的情况?
-- 编辑 --
作为对下面Yakimych答案的回应,我并不是要暗示编译查询与存储过程相同。我正在试图弄清楚如果你已经在应用程序端做了所有可能的优化(在这种情况下是编译查询),那么是否仍需要存储过程。因此,我想知道存储过程比应用程序端优化和参数化查询(有效地是编译查询)的组合更好的原因。
我之所以问这个问题,是因为有很多人似乎认为由于各种原因(即这篇文章),存储过程不再必要。
3个回答

9
首先,编译EF查询与使用存储过程获得的性能优势无关。
根据http://msdn.microsoft.com/en-us/library/cc853327.aspx - 查询对概念模型执行时会发生以下操作:
- 加载元数据 - 打开数据库连接 - 生成视图 - 准备查询 - 执行查询 - 加载和验证类型 - 跟踪 - 实体化对象
关于准备查询的解释如下:
包括组合查询命令的成本,基于模型和映射元数据生成命令树以及定义返回数据的形状。因为Entity SQL查询命令被缓存,所以同一查询的后续执行时间更短。您还可以使用已编译的LINQ查询来减少后续执行的成本。
因此,如果您编译查询并在以后重复使用它,那么您将在每个后续查询执行期间在应用程序中节省此操作的时间。但是,您不会影响针对数据库执行的生成SQL代码。编译查询时获得的性能优势在应用程序级别。
另一方面,如果您对生成的SQL代码不满意并希望在数据库级别上优化性能,则通常会使用存储过程。
编辑以回应您的评论和编辑。
我觉得您认为编译EF查询会以某种方式更改将针对数据库运行的生成SQL代码(您提到编译查询会导致参数化SQL查询?)。事实并非如此。无论您直接运行查询还是使用compiledQuery.Invoke,都将针对DB运行相同的SQL代码。此外,您无法完全控制它,而是依赖ORM以最佳方式生成它。在某些情况下,这不是最佳选择,这就是SP发挥作用的地方。
因此,总结一下:
  • 编译查询纯粹是应用端的优化。它节省了编译在代码中被重复使用的查询所需的时间。
  • 存储过程可用于微调SQL代码,使其尽可能地匹配您的目标,从而提供在数据库级别获得最佳性能的可能性。

绝不是一种技术可以替代另一种技术。


我并不是想暗示编译查询和存储过程是一样的(这就是为什么我提到它们被缓存为参数化查询)。我的意思是,如果你的ORM生成参数化查询(EF或其他任何ORM),是否仍有使用存储过程的理由。如果我的表述不够清晰,我很抱歉,我会更新我的问题以澄清。 - Carvellis
根据您的评论和修改,我编辑了我的回答。(希望我理解正确) - Yakimych
不,我并不认为编译EF查询会改变生成的SQL代码。我知道编译查询与存储过程没有任何关系。重点是,由EF生成的查询(无论是否编译)将像存储过程一样在SQL Server中进行优化和缓存。如果您愿意,我正在寻找两种查询请求样式之间的比较:一方面是存储过程,另一方面是EF生成的(已编译)查询。 - Carvellis
1
如果你意识到编译和非编译查询都会像存储过程一样在 SQL Server 中进行“优化和缓存”,那么为什么问题与编译查询有关?关于实际讨论-在一个情况下,EF将创建并运行参数化查询,在另一个情况下,将调用SP。如果两种情况下的SQL代码相同,则不会有任何显着的性能差异,在这种情况下我同意你的观点-使用SP没有意义。 - Yakimych
我认为他把“编译查询”和“参数化查询”搞混了。 - BlueRaja - Danny Pflughoeft

5
“存储过程是否在某些情况下表现更佳?”
如果使用EF或存储过程生成相似的参数化SQL,它们的执行效率是相同的。但是,DBA可以根据其对DB模式和使用模式的经验进一步优化查询。存储过程使他们能够轻松地在不影响使用它的应用程序的情况下进行优化,而ORM则不能做到这一点。
我们有一个非常复杂的SQL Server数据库,有许多外部系统通过触发器在其中复制数据。对我们来说,使用EF的问题在于当使用任何ORM时,向DB发送的SQL的责任将成为应用程序开发人员的责任,而不是DBA的责任。

2
+1 尽管不幸的是,我曾经工作过的每个需要使用存储过程的工作都让创建/更新它们成为开发人员的工作。 - BlueRaja - Danny Pflughoeft

3

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