最近、SQL で特定のクエリを実行する最善の方法を一生懸命探しています。このクエリは、複数の異なる方法で実行できる可能性があります。調査を進める中で、WHERE IN の概念が本質的に非効率であるため、この概念を嫌う意見がかなり多く見られました。
例えば:WHERE Col IN (val1, val2, val3)
現在のプロジェクトでは、大量のデータに対して UPDATE を実行していますが、次のどちらがより効率的か (または、より良いオプションが存在するかどうか) を考えています。
UPDATE table1 SET somecolumn = 'someVal' WHERE ID IN (id1, id2, id3 ....);
上記では、ID のリストは最大 1.5k 個の ID になります。
VS
コード内のすべての ID をループし、それぞれに対して次のステートメントを実行します。
UPDATE table1 SET somecolumn = 'someVal' WHERE ID = 'theID';
私にとっては、実行するクエリが少ないため、前者の方がより良く/より速く動作する方が論理的に思えます。とはいえ、SQL の詳細やクエリ キューの仕組みについて、私は 100% 精通しているわけではありません。
また、テーブル ロックやその他の一般的なパフォーマンスに関して、どちらが DB にとってよりフレンドリーであるかもわかりません。
役に立つかもしれない一般的な情報として、私は Microsoft SQL Server 2014 を使用しており、主な開発言語は C# です。
どのような助けでも大歓迎です。
編集:
オプション3:
UPDATE table1 SET somecolumn = 'someVal' WHERE ID IN (SELECT ID FROM @definedTable);
上記では、@definedTable は SQL の「ユーザー定義テーブル タイプ」であり、内部のデータは (C# では) SqlDbType.Structured 型としてストアド プロシージャに渡されます。
ID がどのように取り込まれるのかという質問があります。ID はList<string>
コード内にあり、コード内の他の用途に使用され、その後ストアド プロシージャに送信されます。現在、ID は 1 つの列 (ID) のみを持つ「ユーザー定義テーブル タイプ」としてストアド プロシージャに取り込まれています。
コードで巨大な文字列を連結して、それを変数としてSPに吐き出すよりも、テーブルにまとめた方が良いと思いましたid1, id2, id3, id4
。
ベストアンサー1
私は3番目のオプションを使用していますが、うまく機能しています。
私のストアドプロシージャにはテーブル値パラメータ参照テーブル値パラメータを使用する。
手順には、あなたが言ったように、ループのない 1 つのステートメントがあります。
UPDATE table1 SET somecolumn = 'someVal' WHERE ID IN (SELECT ID FROM @definedTable);
プロシージャを 1,500 回呼び出すよりも、1 回呼び出す方が適切です。1,500 回のトランザクションよりも、1 つのトランザクションの方が適切です。
行数が@definedTable
、たとえば 10K を超える場合は、10K ごとに分割することを検討します。
最初のバリアントは、句内の値が少ない場合は問題ありませんIN
が、非常に大きな数値(60K以上)になると、次のようになります。この答え:
メッセージ 8623、レベル 16、状態 1、行 1 クエリ プロセッサの内部リソースが不足したため、クエリ プランを作成できませんでした。これはまれなイベントであり、非常に複雑なクエリ、または非常に多くのテーブルやパーティションを参照するクエリでのみ発生します。クエリを単純化してください。このメッセージが誤って表示されたと思われる場合は、詳細についてはカスタマー サポート サービスにお問い合わせください。