c# - SQL 查询在 .NET 应用程序中很慢,但在 SQL Server Management Studio 中是瞬时的

标签 c# sql-server performance

这是SQL

SELECT tal.TrustAccountValue
FROM TrustAccountLog AS tal
INNER JOIN TrustAccount ta ON ta.TrustAccountID = tal.TrustAccountID
INNER JOIN Users usr ON usr.UserID = ta.UserID
WHERE usr.UserID = 70402 AND
ta.TrustAccountID = 117249 AND
tal.trustaccountlogid =  
(
 SELECT MAX (tal.trustaccountlogid)
 FROM  TrustAccountLog AS tal
 INNER JOIN TrustAccount ta ON ta.TrustAccountID = tal.TrustAccountID
 INNER JOIN Users usr ON usr.UserID = ta.UserID
 WHERE usr.UserID = 70402 AND
 ta.TrustAccountID = 117249 AND
 tal.TrustAccountLogDate < '3/1/2010 12:00:00 AM'
)

基本上有一个 Users 表、一个 TrustAccount 表和一个 TrustAccountLog 表。
用户:包含用户及其详细信息
TrustAccount:一个用户可以拥有多个TrustAccount。
TrustAccountLog:包含对所有 TrustAccount“移动”的审计。一个
TrustAccount 与多个TrustAccountLog 条目关联。 现在,此查询在 SQL Server Management Studio 中以毫秒为单位执行,但由于某些奇怪的原因,它在我的 C# 应用程序中需要很长时间,有时甚至会超时(120 秒)。

这里是代码的简要说明。它在一个循环中被多次调用并且语句被准备好。

cmd.CommandTimeout = Configuration.DBTimeout;
cmd.CommandText = "SELECT tal.TrustAccountValue FROM TrustAccountLog AS tal INNER JOIN TrustAccount ta ON ta.TrustAccountID = tal.TrustAccountID INNER JOIN Users usr ON usr.UserID = ta.UserID WHERE usr.UserID = @UserID1 AND ta.TrustAccountID = @TrustAccountID1 AND tal.trustaccountlogid =  (SELECT MAX (tal.trustaccountlogid) FROM  TrustAccountLog AS tal INNER JOIN TrustAccount ta ON ta.TrustAccountID = tal.TrustAccountID INNER JOIN Users usr ON usr.UserID = ta.UserID WHERE usr.UserID = @UserID2 AND ta.TrustAccountID = @TrustAccountID2 AND tal.TrustAccountLogDate < @TrustAccountLogDate2 ))";
cmd.Parameters.Add("@TrustAccountID1", SqlDbType.Int).Value = trustAccountId;
cmd.Parameters.Add("@UserID1", SqlDbType.Int).Value = userId;
cmd.Parameters.Add("@TrustAccountID2", SqlDbType.Int).Value = trustAccountId;
cmd.Parameters.Add("@UserID2", SqlDbType.Int).Value = userId;
cmd.Parameters.Add("@TrustAccountLogDate2", SqlDbType.DateTime).Value =TrustAccountLogDate;

// And then...

reader = cmd.ExecuteReader();
if (reader.Read())
{
   double value = (double)reader.GetValue(0);
   if (System.Double.IsNaN(value))
      return 0;
   else
      return value;
}
else
   return 0;

最佳答案

根据我的经验,查询在 SSMS 中运行速度快而在 .NET 中运行速度慢的常见原因是连接的 SET-ting 存在差异。当通过 SSMS 或 SqlConnection 打开连接时,会自动发出一堆 SET 命令来设置执行环境。不幸的是,SSMS 和 SqlConnection 具有不同的 SET 默认值。

一个常见的区别是 SET ARITHABORT。尝试将 SET ARITHABORT ON 作为 .NET 代码中的第一个命令发出。

SQL Profiler 可用于监控 SSMS 和 .NET 发出了哪些 SET 命令,以便您发现其他差异。

以下代码演示了如何发出 SET 命令,但请注意,此代码尚未经过测试。

using (SqlConnection conn = new SqlConnection("<CONNECTION_STRING>")) {
    conn.Open();

    using (SqlCommand comm = new SqlCommand("SET ARITHABORT ON", conn)) {
        comm.ExecuteNonQuery();
    }

    // Do your own stuff here but you must use the same connection object
    // The SET command applies to the connection. Any other connections will not
    // be affected, nor will any new connections opened. If you want this applied
    // to every connection, you must do it every time one is opened.
}

关于c# - SQL 查询在 .NET 应用程序中很慢,但在 SQL Server Management Studio 中是瞬时的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2736638/

相关文章:

C#:与 null 比较

c# - 在 DataGridView 列中格式化 TimeSpan

sql-server - 大表分区——索引

java - 用 Java 替换许多文件中的许多字符串标记的最有效方法是什么?

android - 按需加载 Fragment UI

c# - 检查文本框中是否有任何字符

c# - C#中如何设置控件模板

sql - 如何选择该组的日期为空或最大日期的行

sql - 将错误行发送到其他表

python - sqlite 和 python...速度与激情