c# - 如何防止 .NET 变成 EXEC 的 SELECT 语句中的参数嗅探?
问题描述
我有一个 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 访问权限。这是否也意味着他们无法获得统计数据?
解决方案
如果确实是参数嗅探(您必须查看实际计划才能确定),并且您肯定拥有正确的索引,您可以更新查询以使用索引提示,但 IMO 这不是最佳方式. 如果您可以将查询放入存储过程中,则您可以将存储过程标记为 WITH RECOMPILE,因此它不会重用第一个计划。IMO,这比强制索引提示更好。
推荐阅读
- r - R - 来自数据集的自定义概率分布的随机绘图
- java - jboss intellij https 管理接口不支持,请禁用它并改用http管理接口
- opengl-es - 如何模拟 GL_TEXTURE_EXTERNAL_OES 纹理?
- php - Laravel,VueJS应用程序在生产中的空白页面
- python - Python 创建表并保存为 CSV 并显示第一行内容
- java - 操作字符串以创建具有相应索引的新字符串
- javascript - 如何限制可以创建元素的次数
- .net - VB.NET 临时修改循环的起始值?
- python - 如何在 SQL Server 上使用 python odbc DROP TABLE?
- java - Spring boot jackson解析器空指针异常