LINQ-to-Entities如何摆脱sp_executesql

3
我现在正在使用数据库引擎调整顾问来优化我的数据库,但我遇到的问题是,我的SQL Profiler跟踪显示大量使用sp_executesql执行的查询 - 该顾问无法处理这些查询。看起来这些查询来自我使用的LINQ-to-Entities,所以我想知道是否有任何方法使LINQ-to-Entities直接调用语句。
4个回答

6
LINQ/.NET通过将SQL查询作为sp_executesql调用发送到SQL服务器来运行它们。然而,Database Engine Tuning Advisor无法解析通过SQL Server Profiler捕获的这种语句,所以调整会话的结果会很差。
以下是我如何在将它们提供给Database Engine Tuning Advisor之前“拆箱”sp_executesql语句,以便它可以正确地分析它们:
  1. SQL Server Profiler中运行(或打开现有)调整会话后,使用文件>导出>提取SQL Server事件>提取Transact-SQL事件...保存包含所有SQL语句的.SQL文件。
  2. 打开.SQL文件(例如,在Notepad++ 6中 - http://notepad-plus-plus.org/),并运行以下查找和替换正则表达式来拆箱所有的sp_executesql语句为普通TSQL。查找:^EXEC[\s]+SP_EXECUTESQL[\s]+[N]*'((''|[^'])*)'[\s]*,[\s]*[N]*'((''|[^'])*)'[\s]*,[\s]*([^\n]+)$替换:BEGIN\nDECLARE \3\nSELECT \5\n\1\nEND
  3. 接下来,使用我们刚刚构建的“拆箱”后的.SQL文件,在Database Engine Tuning Advisor中查找需要添加的索引。
调整愉快!请注意,我选择了Notepad++ 6(或更高版本),因为它具有非常好的正则表达式实现,其他文本编辑器可能无法运行上述表达式。

1
为什么你不在顶部?这个简单的查找和替换确实起到了作用。除了 EF 在每个过程调用中使用相同的变量名之外。但是这个 ^ 真的很有帮助。谢谢伙计! - Giri
更新“查找”表达式:^EXEC [\ s] + SP_EXECUTESQL [\ s] + [N] '(('''|''|[^'])*)'[\ s] ,[\ s] * [N] '(('''|''|[^']))'[\ s] *,[\ s] *([^\n]+)$ - Fredrik Johansson

4

同意Adam的观点。在实体框架/ADO.net中使用sp_executesql是有意义的。然后,查询类似于参数化存储过程被执行,SQL优化器可以重用查询计划。

如果您想调整您的数据库,您也应该考虑这些查询。我建议您备份您的数据库,使用回放跟踪模板(在您的SQL分析器中)捕获查询,还原您的数据库,运行您的调整顾问设置其工作负载为此跟踪。


3
那只是 RPC 调用在性能分析器中显示的一种现象。根据Free TDS 协议文档,客户端请求有两种主要类型:语言 (类型 0x01) 和 RPC (类型 0x03)。当调用是带有参数的 SQL 批处理时,RPC 调用将是类型为 0x03,长度为 0x0A 的快捷方式,这是一个 sp_executesql 快捷方式。

因此,你会看到,实际发生的情况是,当客户端(任何客户端)提交包含参数的批处理时,它将出现 as if 调用了 sp_executesql。这对于 ODBC、OleDB、SqlClient、Sql Native Client 都是正确的,就像我说的,任何 客户端都是如此。所以不是 Entity Framework 或 ADO.Net 实际上调用了 sp_executesql(事实上,该过程甚至没有真正被调用,尽管该请求执行起来就好像它被调用了。很复杂……)。这是协议的一种现象,每当你向请求添加一个 @parameter 时就会发生。

谢谢您的解释 - 它相当清晰地阐明了事情。现在我明白发生了什么! - Michael Pliskin

2

sp_executesql的使用是ADO.NET效果,而不是特定于Entity Framework的东西。据我所知,没有办法指示它不使用该存储过程。


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