存储过程和实体框架的性能

Posted

技术标签:

【中文标题】存储过程和实体框架的性能【英文标题】:Performance of stored procedures & Entity Framework 【发布时间】:2012-04-18 12:00:22 【问题描述】:

通过我的实体模型调用存储过程会导致比直接调用慢得多的性能有什么明显的原因吗?

首先,我不希望 SP 以完全相同相同的速度运行,而且我知道 EF 必须做的各种事情在直接访问 SP 时不会被调用.

除此之外,我有一个返回三列字符串的查询。当我通过 Enterprise Manager 执行它时,它几乎可以立即运行。如果我通过 EF 运行它,则大约需要六秒钟。当然,结果被映射到一个复杂的类型,但是当我通过 SQL Server Profiler 运行查询时,可以清楚地看到 SQL Server 上发生了延迟:

在图上,1 表示从企业管理器调用的 SQL,2 表示它是通过我的应用程序使用 EF 调用的。

这里有什么明显的我做错了吗?我预计可能会延迟一两秒,但差异似乎太大了。

编辑:

似乎存储过程在通过 ADO.Net 调用时也运行缓慢。我的同事似乎认为这与 .Net 正在缓存的错误执行计划有关。通过编辑存储过程并再次保存它似乎清除了缓存中的任何内容,并且对存储过程的 ADO.Net 和 EF 调用都运行良好。

以前有没有人遇到过这样的事情?

【问题讨论】:

AFAIK,ADO.NET 缓存执行计划。它是 SQL Server。 EF 也有计划缓存的概念,但它指的是查询编译(.NET 表达式 -> T-SQL)而不是 DB 运算符。 您能否确认与通过 SSMS 中的 T-SQL 批处理重复运行该过程相比,通过 EF 重复(循环)运行该过程总是需要更多时间?您是否在 SQL Profiler 中观察到这种差异? 【参考方案1】:

看看this thread on SQL Server forum。这有点相似,可能会提供一些线索。简而言之,您可能在 SSMS 和 ADO.NET 中有不同的 SQL Server 执行环境选项,从而导致不同的执行计划。清除 SQL Server 计划缓存应该会有所帮助。

【讨论】:

这就是解决方案。除了 arithabort,还有其他选项,例如 ansi_nulls。我建议您检查所有这些。 @Pavel - 感谢您的回答,似乎确实如此。我在下面添加了对我的发现的更完整的解释,希望这对其他人有所帮助。【参考方案2】:

Pavel Gatilov 似乎已经用 ARITH ABORT 设置击中了这个名字,但我想我会发布更多关于我的发现的信息。

This post 在 SO 上讨论了一个类似的问题并讨论了解决方法;可以在 EF 连接和 SQL.Data.Client 之间编写一个包装类,该类在对数据库的任何调用前加上“SET ARITHABORT ON”。 MSDN 上的This article 有更详细的解释。

查看了更改的复杂性并考虑到我们要将应用程序从使用存储过程转移到完全使用 EF,我们将硬着头皮将 SP 功能转移到我们的 EF 数据模型中。

【讨论】:

请注意,EF 不擅长生成最佳查询,因此出于性能原因,您可能必须保留一些 SP。【参考方案3】:

在单个事务中调用不一样

INSERT INTO foo (col1, col2) SELECT col1, col2 (with all 100 rows of the changes)

比调用100次

EXEC SP_foo_INSERT param1, param2

只需查看在这两种情况下生成的查询,然后直接在数据库中测试该查询即可。看看它的执行计划是什么。

【讨论】:

以上是关于存储过程和实体框架的性能的主要内容,如果未能解决你的问题,请参考以下文章

实体框架与 NHibernate - 性能

带有存储过程的实体框架 VS LINQ to SQL VS ADO.NET? [关闭]

存储过程参数名称和实体框架

使用实体框架和存储过程进行并发检查

在实体框架中使用存储过程

使用实体框架核心生成和访问存储过程