web-dev-qa-db-ja.com

ループのカーソルではなく、トップクエリと一時テーブルを選択するのはなぜですか?

T-SQLで大量のデータをループする場合、インターネットで目にするほとんどの例では、次のようなパターンを使用しています。

declare @someVariable int
declare @remainingRows int

select someColumn from someTables into #someTempTable

select @remainingRows = count(*) from #someTempTable
while @remainingRows > 0 begin

    select top 1 @someVariable = someColumn from #someTempTable

    -- Do stuff

    delete top 1 from #someTempTable

    select @remainingRows = count(*) from #someTempTable
end

これは、次のようなカーソルを使用するサンプルよりもはるかに一般的なようです。

declare @someVariable int

select someColumn from someTables into #someTempTable

declare @someCursor cursor for select someColumn from #someTempTable
open @someCursor
fetch next @someVariable from @someCursor

while @@fetch_status = 0 begin

    -- Do stuff

    fetch next @someVariable from @someCursor
end

close @someCursor

パフォーマンスの理由について言及することもありますが、私には直観に反しています。一連のデータを繰り返し処理する前方専用の読み取り専用カーソルは、一時テーブルを常にクエリして更新するよりもはるかに効率的ではないでしょうか。間違ったオプションを使用してテーブルを反復するカーソルであった場合、更新のためにテーブルがロックされる可能性がありますが、非共有の一時テーブル上のカーソルには問題がないと思いますか?

ボーナス質問;カーソルに問題がなければ、スナップショット分離を使用する通常のクエリにカーソルを合わせても安全です。一時テーブルを手動で作成する煩わしさを回避できます。

DECLARE @someCursor CURSOR LOCAL FORWARD_ONLY STATIC READ_ONLY FOR 
SELECT something
FROM tables
5
Jacob

いいえ、ループの方がカーソルよりも速いとは限りませんが、ループの方が快適な場合もあります。自分で一度にループ書き込みフェーズを経験しました。また、カーソルにはいくつかの種類があるため、正しいタイプのカーソルを選択することは重要な詳細です。

Aaron Bertrand(2012年から)は、次の場所でいくつかの比較テストを実施したため、おそらくあなたの質問に回答しています。

つまり、適切なカーソルがいくつかのループ構造よりも大幅に高速に実行されることがわかりました。

彼の比較を読むと、カーソルに慣れるのに役立ちます。

しかし、それらが必要なときだけ。

9
RLF