0

私はかなり奇妙な問題に遭遇しました:

私はSQLサーバーコマンドを動的に形成し、その一部はLIKEテストのグループであり、いくつかの列とテーブルでテキスト検索として使用されます。次のようになります。

SET @text = '%' + REPLACE(REPLACE(REPLACE(@text, '!', '!!'), '%', '!%'), '_', '!_') + '%'

INSERT INTO
  @textFiltered
FROM
  @documents d 
  LEFT JOIN docData t1 WITH (NOLOCK)
    ON t1.ID = d.ID AND
       (t1.Topic like @text escape '!'
        OR t1.Subject like @text escape '!')
  LEFT JOIN docData2 t2 WITH (NOLOCK)
    ON t2.ID = d.ID AND 
       t2.Name like @text escape '!'
WHERE
  t1.ID IS NOT NULL 
  OR t2.ID IS NOT NULL

(確かに、それはテキスト検索を行う最良の方法ではありませんが、それでも重要ではありません)

さて、C# で SQLCommand を作成すると、次のようになります。

using (var cmd = new SqlCommand())
{
   cmd.CommandText = cmdText;
   cmd.CommandType = CommandType.Text;
   cmd.Connection = connection;
   cmd.Parameters.Add("text", NVarChar, 4000).Value = searchText;
   var reader = cmd.ExecuteReader();
   ....
}

実行のパフォーマンスは非常に低く (たとえば 8 秒)、SQL Management Studio で同じクエリを実行するとはるかに高速です (たとえば 500 ミリ秒)。ただし、テキストをパラメーターとして渡す代わりに、次のように SQL のテキストに埋め込む場合:

DECLARE @text nvarchar(max)
SET @text = '<embedded-text>'

その後、SqlCommand も高速に実行されます。さらに奇妙なことに、この動作は LIKE 句で使用される列のセットと相関しているようです (方法はわかりませんでした)。これらの列の型は、nvarchar(size)、nvarchar(max)、ntext のいずれかです。

問題はパラメーターにあると思われます-おそらくタイプが間違っているか、そうでない可能性があります。

PSサイズ=検索テキストの長さ+ 1でパラメーターを作成しようとしました-役に立ちませんでした。

4

1 に答える 1

0

私の最善の推測は、SQL Server が選択しているクエリ プランに関連しているということです。SQLサーバーが既存の統計に対して評価できる定数varcharを使用することと、サーバーが何も知らない任意の変数を使用することには大きな違いがあります。

OPTION (RECOMPILE) ヒントを試すことができます。このヒントにより、すべての呼び出しでストアド プロシージャがコンパイルされますが、SQL Server が指定された値の最適な計画を検索できるようになります。おそらく、あなたの場合は良いトレードオフになります。

ストアド プロシージャの両方のオプションにクエリ プランを追加することもできます。おそらく誰かが違いを確認し、正確な問題を突き止めることができます。

于 2013-03-04T15:51:11.873 に答える