【问题标题】:How do I prevent parameter sniffing in a SELECT statement that .NET is turning into an EXEC?如何防止 .NET 变成 EXEC 的 SELECT 语句中的参数嗅探?
【发布时间】:2019-02-11 23:49:00
【问题描述】:

我有一个 SQL SELECT 语句,它在 SQL Server Management Studio 中运行得非常快(5 秒),但在我的 ASP.NET 代码中运行得非常慢。

我听说这可能与参数嗅探有关。当我从 SSMS 运行 SELECT 语句时,我使用的是 SELECT。但是当我观看 SQL Profiler 时,我的 SELECT 语句作为存储过程执行,其模式为: exec sp_executesql N'SELECT foo FROM bar WHERE userid = @userid',N'@userid int',@userid=2

此 ASP.NET 代码在四分钟后超时(连接字符串设置):

SqlCommand objCommand = new SqlCommand("SELECT foo FROM bar WHERE userid = @userid", objCS);
SqlDataReader reader;
objCommand = new SqlCommand("", objCS);
objCommand.CommandType = CommandType.Text;
objCommand.Parameters.Add("@userid", SqlDbType.Int).Value = 1;
SqlDataReader reader = objCommand.ExecuteReader();

//objCommand.ExecuteReader() 超时;

此代码在 5 秒内在 SQL Server Management Studio 中执行:

DECLARE @userid AS Int = 2
SELECT foo FROM bar WHERE userid = @userid

在 5 秒内返回 60000+ 行。

如何使 ASP.NET 代码作为 SELECT 语句而不是存储过程执行,同时保留参数化存储过程的安全值?

编辑:我认为这可能与使用 SQL 语句运行代码的不同用户与在 SSMS 中运行 SQL 语句的用户有关。从代码运行的用户具有不同的服务器权限,包括对表的有限访问。 SQL 语句包含一个视图,并且用户没有对该视图中所有表的基础 SELECT 访问权限。这是否也意味着他们无法访问统计数据?

【问题讨论】:

  • 作为推论,此查询在 SSMS 中运行 16 秒:DECLARE @userid AS Int = 1
  • 我怀疑它是否会因为用户 ID 不同而创建不同的计划。您有多确定在使用sp_executesql 时它会产生不同的计划?您可以通过使用 ssms 中的不同用户 ID 使用 sp_executesql 执行查询来快速测试您的假设。
  • 阅读this article

标签: c# sql asp.net sql-server


【解决方案1】:

如果它确实是参数嗅探(您必须查看实际计划来确定),并且您确定您有正确的索引,您可以更新您的查询以使用索引提示,但 IMO 是不是最佳方式。如果您可以将查询放入存储过程中,则您可以将存储过程标记为 WITH RECOMPILE,因此它不会重用第一个计划。 IMO,这比强制索引提示更好。

【讨论】:

    【解决方案2】:

    您的问题与参数嗅探无关。但是使用 SSMS 和后端设置选项。 每当您从 SSMS 执行语句时,它都会使用 SSMS 定义的属性。你可以在

    中看到

    工具 >> 选项 >> 查询执行 >> SQL Server >> 高级

    您将在 SSMS 中启用 SET ARITH_ABORT 选项。但你没有在你的程序中。 因此,在您的程序中添加以下行并再次测试。

    SET ARITHABORT ON
    

    我对你的问题很有信心,这个问题会解决的。

    【讨论】:

    • ...这里没有存储过程。
    • 那么你可以在后端定义这个参数或者添加查询。
    • 杰瑞,感谢您的评论。 SET ARITHABORT ON 不会更改 ASP.NET 代码中的查询执行时间。从代码执行时仍然超时。
    猜你喜欢
    • 2019-01-18
    • 1970-01-01
    • 2015-04-26
    • 2012-03-05
    • 1970-01-01
    • 2014-09-28
    • 2016-10-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多