4

小さなログ処理アプリケーションから実行する単純なクエリだと思っていたものがあります。このメソッドの目的は、単純にログ テーブルから最も高い日付値を取得することです。

private DateTime GetLastEntryDate(string serverName, string siteName)
{
    DateTime dt = DateTime.MinValue;
    using (var con = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["LogParserDB"].ConnectionString))
    {
        con.Open();
        using (var cmd = new SqlCommand("SELECT MAX(date) FROM iislogs WHERE host=@Host AND site=@Site", con))
        {
            cmd.CommandTimeout = 120;
            cmd.Parameters.AddWithValue("Host", serverName);
            cmd.Parameters.AddWithValue("Site", siteName);
            var result = cmd.ExecuteScalar();
            if (result != DBNull.Value)
            {
                dt = (DateTime)result;
            }
        }
    }
    return dt;
}

テーブルにはいくつかのインデックスがありますが、それが関連しているかどうかはわかりません。問題は、このコードを実行すると、2 分後にタイムアウトが発生することですExecuteScalar

そのクエリをコピーして同じパラメーターを使用して SSMS に貼り付けると、00:00:04 または 00:00:00 (統計を更新したばかりの場合) で完了します。

SELECT MAX(date) FROM iislogs WHERE host='servername' AND site='W3SVC1'

ブロッキングを確認しましたが、そのようなものは何も表示されません。そのデータベースは、この 1 つのアプリによってのみアクセスされており、マルチスレッドなどではありません。


更新: 興味深いことに、Profiler によってキャプチャされた正確なクエリを実行すると、SSMS でも時間がかかります。

exec sp_executesql N'SELECT MAX(date) FROM iislogs WHERE host=@Host AND site=@Site',N'@Host nvarchar(13),@Site nvarchar(6)',@Host=N'servername',@Site=N'W3SVC1'

実際の列はそれぞれvarchar(50)varchar(10)です。

4

1 に答える 1

5

SSMS で実行するクエリ

SELECT MAX(date)
FROM   iislogs
WHERE  host = 'servername'
       AND site = 'W3SVC1' 

アプリケーションによって実行されるものと同じではありません。

EXEC sp_executesql
  N'SELECT MAX(date) FROM iislogs WHERE host=@Host AND site=@Site',
  N'@Host nvarchar(13),@Site nvarchar(6)',
  @Host=N'servername',
  @Site=N'W3SVC1' 

最初のものにはvarchar文字列リテラルがあります。2 番目のものにはnvarcharパラメータがあります。実際、列のデータ型はvarchar.

nvarcharよりもデータ型の優先順位が高いvarcharため、列の暗黙的なキャストを強制しています。これにより、列のインデックスが役に立たなくなります。

アプリケーションのパラメーターのデータ型を次のように変更します。varchar

于 2013-06-19T10:18:01.013 に答える