【问题标题】:Can you force Linq2SQL to NOT use sp_executesql?你能强制 Linq2SQL 不使用 sp_executesql 吗?
【发布时间】:2011-12-31 02:34:09
【问题描述】:

所以我写了一个 Linq 查询,它需要 16 秒才能运行。决定查看查询计划是什么,所以我从 Linq to SQL Profiler 中得到它,查询只需要 2 秒即可运行。 叹息

在花了一天的大部分时间研究事情并最终开始使用 SQL Server Profiler 之后,我发现 Linq2SQL 正在使用 sp_executesql 来运行查询。我知道它应该提高性能,因为它更有可能重用执行计划......但它似乎选择了一个可怕的执行计划来使用。

奇怪的是,只有加入特定表时它才会变慢,而且我不知道为什么该特定表会导致问题。

编辑只是为了澄清这里的实际问题:

它实际上涉及不同的查询。一种是,本质上,

SELECT col1, col2, ... FROM table1, table2 WHERE table1.val IN (1234, 2343, 2435)

另一个是

EXEC sp_executesql 'SELECT col1, col2, ... FROM table1, table2 WHERE table1.val IN (@p1, @p2, @p3)', 
N'@p0 int,@p1 int,@p2 int,@p3 int',
@p0=1234, @p1=2343, @p3=2435

【问题讨论】:

  • 那你为什么要使用 LINQ? LINQ 非常适合基础知识。如果您需要调整查询,请查询 SQL。 .NET 可以直接与 SQL 对话。
  • 但我不需要调整查询...查询本身可以正常工作。
  • 确保你加入的表有正确的索引,并且主要在你加入的列上。
  • 您的统计数据是最新的吗?

标签: sql-server-2005 tsql linq-to-sql


【解决方案1】:

您的问题并非源于使用 sp_executesql,因此规避它(您不能)不会解决您的问题。我建议你阅读 Erland Sommarskog 的优秀文章:

Slow in the Application, Fast in SSMS?
Understanding Performance Mysteries

这将使您深入了解为什么会出现性能差异、如何诊断和持续重现它,以及最后如何解决它。

【讨论】:

    【解决方案2】:

    如果完全相同的查询在一个应用程序或服务器上速度很快,但在另一个应用程序或服务器上速度很慢,这通常与执行计划有关。执行计划是服务器用来运行查询的蓝图。该计划应该被创建一次,然后重复用于所有仅参数值不同的查询。

    不同的执行计划会导致性能大相径庭,100 的系数一点也不稀奇。作为第一步,检查执行计划是否不同。探查器事件performance -> showplan xml 记录计划。

    如果计划不同,一个可能的原因可能是会话选项,例如ansi nulls

    SET ANSI_NULLS 
    

    另一种可能性是不同的登录(蓝图包含安全信息,因此每个安全上下文都有自己的一组缓存执行计划。)

    清除计划缓存的最简单方法是重新启动 SQL Server 服务。还有一个高级命令clear the entire query plan cache

    DBCC FREEPROCCACHE
    

    附:如果您有一个存储过程根据参数的值执行不同的操作,那么值得查看parameter sniffing。但由于您从分析器复制完全相同的过程,我假设参数对于慢速和快速调用都是相同的。

    【讨论】:

    • 我会想到参数嗅探。对于慢速和快速调用,OP 使用相同的参数调用是无关紧要的。参数嗅探的整个问题在于,它会为它看到的 first 很多参数值编译计划,然后重新使用它。当粘贴到 SSMS 中时,因为 ARITH_ABORT 具有不同的默认选项,它不会重用应用程序使用的缓存计划,但会生成一个为 OP 当前正在调查的参数值量身定制的新计划。因此性能更好。
    • @MartinSmith:问题是相同的参数值存在性能差异。嗅探怎么能解释呢?
    • 因为从应用程序运行时,它可能会重新使用为一组不同的参数值编译的计划。 OP 可以通过检索执行计划并查看 XML 中的“参数编译值”来验证这一点
    • @MartinSmith:如果计划是针对一组不同的参数编译的,那可以解释为什么调用很慢。但它无法解释为什么两个相同参数的调用具有不同的性能。
    • 因为他们没有使用相同的计划。 SSMS 对ARITH_ABORT 选项有不同的默认设置。这是用作计划缓存键的设置之一,这意味着具有不同on/off 设置的连接不能重用彼此的计划。在 OP 将问题查询粘贴到并运行它之前,缓存中可能没有预先存在的计划适用于 SSMS 连接,因此它会生成一个适合这些值的新计划。
    【解决方案3】:

    回答你的问题....

    不,你不能……

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-30
      • 2017-01-01
      • 2014-03-10
      • 1970-01-01
      • 1970-01-01
      • 2018-07-23
      • 1970-01-01
      相关资源
      最近更新 更多