Entity framework 实体框架4.2 exec sp_executesql不使用索引(参数嗅探)

Entity framework 实体框架4.2 exec sp_executesql不使用索引(参数嗅探),entity-framework,sql-server-2008-r2,sp-executesql,parameter-sniffing,Entity Framework,Sql Server 2008 R2,Sp Executesql,Parameter Sniffing,在运行SQLServer2008R2的实体框架(4.2)生成的简单SQL查询中,我遇到了一些主要的性能问题。在某些情况下(但不是全部),EF使用以下语法: exec sp_executesql 'DYNAMIC-SQL-QUERY-HERE', @param1... 在其他情况下,is只执行原始SQL,并将提供的参数烘焙到查询中。我遇到的问题是,使用sp_executesql执行的查询忽略了目标表上的所有索引,导致查询的性能极差(通过检查SSMS中的执行计划确认) 经过一点研究,这个问题听起来

在运行SQLServer2008R2的实体框架(4.2)生成的简单SQL查询中,我遇到了一些主要的性能问题。在某些情况下(但不是全部),EF使用以下语法:

exec sp_executesql 'DYNAMIC-SQL-QUERY-HERE', @param1...
在其他情况下,is只执行原始SQL,并将提供的参数烘焙到查询中。我遇到的问题是,使用sp_executesql执行的查询忽略了目标表上的所有索引,导致查询的性能极差(通过检查SSMS中的执行计划确认)

经过一点研究,这个问题听起来可能是由“参数嗅探”引起的。如果我像这样附加选项(重新编译)查询提示:

exec sp_executesql 'DYNAMIC-SQL-QUERY-HERE OPTION(RECOMPILE)', @param1...
使用目标表上的索引,查询执行速度非常快。我还尝试切换用于在数据库实例()上禁用参数嗅探(4136)的跟踪标志,但是这似乎没有任何效果

这给我留下了几个问题:

  • 是否仍然需要将选项(重新编译)查询提示附加到实体框架生成的SQL中
  • 是否存在阻止实体框架使用exec sp_executesql,而只运行原始SQL的方法
  • 还有其他人遇到这个问题吗?还有其他提示吗
  • 其他信息:

  • 我确实通过SSMS重新启动了数据库实例,但是,我将尝试从服务管理控制台重新启动服务
  • 参数化设置为简单(是否强制参数化:0)
  • “针对特定工作负载优化”具有以下设置
    • 数值:0
    • 最低:0
    • 最高限额:1
    • 正在使用的值:0
    • 是动态的:1
    • 是否先进:1
  • 我还应该提到,如果在使用下面的脚本启用跟踪标志4136后,通过服务管理控制台重新启动SQL Server服务,似乎实际上清除了跟踪标志…也许我应该用另一种方式来执行此操作

    DBCC TRACEON(4136,-1)
    

    在这一点上,我建议:


    将“为临时工作负载优化”设置设置为true

    EXEC sp_configure 'show advanced', 1;
    GO
    RECONFIGURE WITH OVERRIDE;
    GO
    EXEC sp_configure 'optimize for ad hoc', 1;
    GO
    RECONFIGURE WITH OVERRIDE
    GO
    EXEC sp_configure 'show advanced', 0;
    GO
    RECONFIGURE WITH OVERRIDE;
    GO
    

    如果过了一段时间,这个设置似乎没有什么帮助,只有到那时我才会尝试跟踪标志的额外支持。这些通常是作为最后手段保留的。通过SQL Server Configuration Manager使用命令行设置跟踪标志,而不是在查询窗口中使用全局标志。见

    tl;dr

    更新统计信息


    我们有一个带有一个参数(主键)的
    delete
    查询,当通过EF和
    sp_executesql
    调用时,需要约7秒才能完成。手动运行查询,并将参数嵌入到
    sp_executesql
    的第一个参数中,可使查询快速运行(~0.2秒)。添加
    选项(重新编译)
    也有效。当然,这两种变通方法对我们来说都不可用,因为我们使用的是EF

    可能是由于级联外键约束,长时间运行的查询的执行计划非常庞大。当我查看SSMS中的执行计划时,我注意到在某些情况下,不同步骤之间的箭头比其他步骤更宽,这可能表明SQL Server在做出正确决策时遇到了困难。这让我想到了统计学。我查看了执行计划中的步骤,以查看可疑步骤中涉及的表。然后,我为该表运行了
    updatestatistics Table
    。然后我重新运行了错误的查询。我又重新运行了一遍。再一次只是为了确定。成功了。我们的表现恢复正常。(仍然比非
    sp_executesql
    性能稍差,但是嘿!)


    事实证明,这只是我们开发环境中的一个问题。(这是一个大问题,因为它使我们的集成测试花费了很长时间。)在我们的生产环境中,我们有一个定期更新所有统计数据的作业。

    关于EF,我无法回答任何问题(对不起,我从未接触过它),但我还有其他问题需要回答:设置跟踪标志后是否重新启动了服务?您在数据库级别对参数化(简单或强制-请参阅
    sys.databases.is_parametering_forced
    )的设置是什么?“针对临时工作负载进行优化”的sp_配置设置是什么?不幸的是,如果我没记错的话,开箱即用的EF将为N'foo'和N'blat'等参数生成两种不同的计划,因为它们的长度不同。我对延迟响应表示歉意,并感谢您的快速评论!我已经在原来的帖子中添加了额外的信息,所以我会再次尝试您的测试,将(a)参数化设置为强制(b)针对临时工作负载进行优化设置为1,(c)两者都设置为1。很可能(b)将有助于这种情况,但(a)也可能有帮助。我承认我没有用(a)进行过很多测试,但是(b)帮助了我曾经尝试过的每一个临时工作负载。我们这里有同样的问题。下面被接受的答案对我们来说并不适用……当它起作用时,它就起作用了,但并不总是起作用——仍然没有“好办法”将提示从EF传递到SQL Server。