0

.NET 4.0 を使用して、次の sqlcommand を定義しました。何も変更せずに sqlcommand を連続して複数回実行すると、SQL Server はクエリ プランのキャッシュを拒否します。

string[] colors = new string[] { "red", "blue", "yellow", "green" };
string cmdText = "SELECT * FROM ColoredProducts WHERE Color IN ({0})";

string[] paramNames = tags.Select(
    (s, i) => "@color" + i.ToString()
).ToArray();

string inClause = string.Join(",", paramNames);
using (SqlCommand cmd = new SqlCommand(string.Format(cmdText, inClause))) {
    for(int i = 0; i < paramNames.Length; i++) {
       cmd.Parameters.AddWithValue(paramNames[i], tags[i]);
    }
    //Execute query here
}

次のクエリが連続して実行された後、わずかな時間で実行されていたため、プランのキャッシュを拒否していることがわかります。

string[] colors = new string[] { "red", "blue", "yellow", "green" };
string cmdText = "SELECT * FROM ColoredProducts WHERE Color IN ({0})";

string inClause = string.Join(",", colors);
using (SqlCommand cmd = new SqlCommand(string.Format(cmdText, inClause))) {
       //Execute query here
}

私の実際のテスト ケースでは、param リストは正確に 2000 のサイズに固定されています。最適化しようとしているシナリオは、非常に大きなテーブルから 2000 レコードの特定のセットを選択することです。クエリをできるだけ高速にしたいので、本当にキャッシュしたいです。

Sleepy post Edit: 問題は、なぜこのプランがキャッシュされないのかということです。はい、sys.dm_exec_cached_plans と sys.dm_exec_sql_test を使用して、クエリがキャッシュにないことを確認しました。

4

1 に答える 1

1

テーブル値パラメーターを使用したアイデアを次に示します。このアプローチが巨大な文字列よりも優れているかどうかをお知らせください。他のアイデアもありますが、これは色のセットを配列として扱うことに最も近いものです。

SQL Server の場合:

CREATE TYPE dbo.Colors AS TABLE
(
  Color VARCHAR(32) -- be precise here! Match ColoredProducts.Color
     PRIMARY KEY
);
GO

CREATE PROCEDURE dbo.MatchColors
  @colors AS dbo.Colors READONLY
AS
BEGIN
  SET NOCOUNT ON;

  SELECT cp.* -- use actual column names please!
  FROM dbo.ColoredProducts AS cp -- always use schema prefix
  INNER JOIN @colors AS c
  ON cp.Color = c.Color; 
END
GO

今C#で:

DataTable tvp = new DataTable();
tvp.Columns.Add(new DataColumn("Color"));

tvp.Rows.Add("red"); 
tvp.Rows.Add("blue"); 
tvp.Rows.Add("yellow"); 
tvp.Rows.Add("green"); 
// ...

using (connectionObject)
{
    SqlCommand cmd = new SqlCommand("dbo.MatchColors", connectionObject);
    cmd.CommandType = CommandType.StoredProcedure;
    SqlParameter tvparam = cmd.Parameters.AddWithValue("@colors", tvp);
    tvparam.SqlDbType = SqlDbType.Structured;
    // execute query here
}

INC# コード内の実際の文字列の長さに関係なく、多数のパラメーターを含むリストよりも優れたパフォーマンスを発揮することはほぼ保証できます。

于 2012-05-01T04:11:57.453 に答える