14

在实体框架(或 linq-to-sql)中结合 SQL Server 使用编译查询时,使用存储过程实际上是否还有性能优势?

编译后的查询将被缓存为参数化查询,因此性能应该接近于存储过程。是否存在存储过程会执行得更好的情况?

- 编辑 -

在回应 Yakimych 下面的回答时,我并不是要暗示编译查询与存储过程相同。如果您在应用程序端完成了所有可能的优化(在本例中为编译查询),我试图弄清楚是否仍然需要存储过程。所以我想我正在寻找为什么存储过程比应用程序端优化和参数化查询的组合更好的原因(这是有效的编译查询)。

我问这个的原因之一是因为有很多人似乎认为由于不同的原因(即这篇文章)不再需要存储过程。

4

3 回答 3

9

首先,编译 EF 查询与使用存储过程可以实现的性能优势无关。

根据http://msdn.microsoft.com/en-us/library/cc853327.aspx - 当针对概念模型执行查询时会发生以下操作:

  • 加载元数据
  • 打开数据库连接
  • 生成视图
  • 准备查询
  • 执行查询
  • 加载和验证类型
  • 追踪
  • 物化对象

以及有关的解释Preparing the query

包括编写查询命令、基于模型和映射元数据生成命令树以及定义返回数据的形状的成本。因为 Entity SQL 查询命令被缓存,相同查询的以后执行花费更少的时间。您还可以使用已编译的 LINQ 查询来降低以后执行的成本。

因此,如果您编译查询并在以后重新使用它,那么您会在每次后续查询执行期间节省应用程序中此操作的时间。但是,您不做的是不影响针对数据库执行的生成的 SQL 代码。编译查询时获得的性能优势是在应用程序级别。

另一方面,您通常会使用存储过程,以防您对生成的 SQL 代码不满意并希望在数据库级别优化性能。

编辑以回应您的评论和编辑。

在我看来,您的印象是编译 EF 查询会以某种方式更改将针对数据库运行的生成的 SQL 代码(您提到编译的查询会导致参数化的 SQL 查询?)。事实并非如此。无论您是直接运行查询还是使用查询compiledQuery.Invoke都将对数据库运行相同的 SQL 代码。此外,您无法完全控制它,而是依靠 ORM 以最佳方式生成它。在某些情况下,它不是最优的,这就是 SP 的用武之地。

所以总结一下:

  • 编译查询纯粹是应用程序端的优化。它节省了编译在代码中重复使用的查询的时间。
  • 存储过程可用于调整您的 SQL 代码并使其尽可能接近您的目标,从而提供在数据库级别获得最佳性能的可能性。

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

于 2010-09-27T09:35:50.567 回答
5

“在任何情况下存储过程会执行得更好吗?”

给定在 EF 或存储过程中生成的可比较的参数化 SQL,它们将执行相同的操作。

但是,DBA 总是有机会根据他们对 DB 模式及其使用模式的经验进一步优化查询。存储过程允许他们在隔离使用它的应用程序的情况下轻松地做到这一点,而 ORM 则不然。

我们有一个极其复杂的 SQL Server 数据库,其中有许多外部系统通过触发器将数据复制进出。EF 对我们的问题是,在使用任何 ORM 而不是 DBA 时,对 DB 触发的 SQL 的责任将成为应用程序开发人员的责任。

于 2010-09-27T14:42:51.477 回答
3

来自知名专家的一些固定答案: Paul Nielsen为什么使用存储过程?

Adam Machanic:不,存储过程还不错

于 2010-09-27T15:03:14.750 回答