我目前正在调用一些 .NET 代码中的几个存储过程,SqlConnection
。我想禁用 SQL Server 完成的缓存,以便我可以定期测量性能(我将把它与另一台可能也没有任何缓存数据的服务器进行比较)。这是否可以在不修改存储过程的情况下完成?
这是我目前使用的代码:
using (SqlConnection connection = new SqlConnection(/* connection string goes here */)) {
SqlCommand command = new SqlCommand(procName, connection);
command.Parameters.AddRange(parameters);
command.CommandType = System.Data.CommandType.StoredProcedure;
connection.Open();
SqlDataReader r = command.ExecuteReader();
// todo: read data here
r.Close();
connection.Close();
}
最佳答案
首先,通过此处的“缓存”,我假设您指的是执行计划缓存。一旦 SQL Server 计算出执行语句的最佳顺序,它就会存储一段时间。这个问题通常被称为“参数嗅探”。这是您在运行 dbcc freeproccache
时清除的内容。不幸的是,这是一个具有管理员权限的命令,它会影响所有连接。
问题的根源在于您的 SQL 可能会因一组不同的参数而执行不同的操作。 SQL Server 只会存储它看到的第一次执行的执行计划和与之关联的参数。因此,如果第一次执行时的论点适用于常见情况,您的应用程序将执行良好。但有时,第一次执行时会使用错误的参数,导致整个应用程序性能不佳。
有很多方法可以优化您的 SQL 语句以减少这种影响,但这并不是完全可以避免的。
- 动态生成 SQL - 每次执行时生成查询计划都会对性能造成影响,但如果使用错误的执行计划导致查询永远不会返回,这可能是值得的。我建议这条路,虽然它更麻烦。我发现
SET STATISTICS TIME ON
和 SQL Profiler 有助于减少计划生成时间。最大的改进来自对表使用三部分命名 (owner.schema.table
)。 - 使用查询提示为您的查询指定一组“好的”初始参数。
SELECT Col1, Col2
FROM dbo.MySchema.MyTab
WHERE Col1=@Parameter
OPTION (OPTIMIZE FOR (@Parameter='value'));
此链接描述了 parameter sniffing problem相当好。这在 SQL 2005 中是一个更大的问题。后来的 SQL 版本更好地避免了这个问题。
关于c# - 通过 .NET 代码禁用 SQL Server 的缓存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34912319/