web-dev-qa-db-ja.com

カーソルを閉じて割り当てを解除するのを忘れるとどうなりますか?

カーソルを開いたままにすることは悪い習慣として知られています。しかし、それを閉じたり、割り当てを解除したりすると、どうなりますか? SQL Server、接続/セッションにどのように影響しますか?クエリ、ストアドプロシージャ、およびカーソルを使用したトリガーの結果に違いはありますか?

32
Mike

カーソルをローカルに宣言したか、グローバルに宣言したかによって異なります(また、環境のデフォルトは何ですか。デフォルトはグローバルですが、変更できます)。

カーソルがグローバルである場合、作成されたスコープ内の最後のコードが操作されるまで、SQL Server内でカーソルは「生きたまま」になります。たとえば、グローバルカーソルを作成するストアドプロシージャを呼び出してから、他の20のストアドプロシージャを呼び出すと、呼び出し元がスコープ外になるまで、他の20のストアドプロシージャが実行されている間、カーソルは存続します。接続レベルではなく、セッションレベルで生き続けると思いますが、これを徹底的にテストしていません。カーソルがローカルとして宣言されている場合、カーソルは現在のオブジェクトのスコープ内にとどまるはずです(ただし、これは理論上のものであり、広範囲にわたる低レベルのメモリテストを行って確認していません)。

ただし、一般的な概念は次のとおりです。何かを終えたら、そのように言います。

カーソルをできるだけ効率的にするために、私は常に次の宣言を使用します。

DECLARE c CURSOR
  LOCAL STATIC FORWARD_ONLY READ_ONLY
  FOR SELECT ...

CLOSEのみ、またはDEALLOCATEのみの場合、メモリの問題が発生する可能性があることも聞いたので、完了したら常に両方を行います。

CLOSE c;
DEALLOCATE c;

しかし、この構文のクリーンアップが問題となる場合、カーソルはいくつありますか?システムに何百ものカーソルがある場合、それは確かに私にとって赤信号です。

[〜#〜]編集[〜#〜]

補足として、カーソル自体は悪くないことを明確にしたいだけです。しかし、それらはしばしば誤用され、乱用されます-より効率的なセットベースのソリューションcouldが実装されている場合に実装されますが、クエリの作成を担当する人は手続き的にしか考えられませんでした。カーソルが意味を持ついくつかのケース:

  • 累計。私のテストでは、カーソルはすべてのSQL 2012より前のセットベースのソリューション(少なくとも文書化され、サポートされているもの)を消去します。
  • さまざまな管理タスク。テーブルのすべての行、またはすべてのテーブルまたはデータベースのストアドプロシージャを呼び出します。
  • セットベースの代替が非常に複雑な場合、またはタスクが1回限りの場合。
30
Aaron Bertrand

カーソルをクローズしないと、カーソルが配置されている行で保持しているロックがアクティブのままになります。参照を閉じた後でも、カーソルが使用しているデータ構造への参照が保持されます(したがって、再度開くことができます)これらの構造はSQLサーバー固有であり(メモリ領域やハンドルだけではない)、カーソルが実際に何であるかに依存しますしますが、通常は一時テーブルまたはクエリ結果セットになります。

AFAIKの割り当てを解除しないのは、パフォーマンスのみです。前述のリソースは割り当てられたままなので、サーバーのパフォーマンスに悪影響を及ぼします。

(開いているか閉じているが割り当て解除されていない)カーソルから割り当てられたリソースは、セッション(または接続)が閉じられるまで割り当てられたままになります

6
Dirk

「カーソル変数を明示的に割り当て解除する必要はありません。変数は、スコープ外になると暗黙的に割り当て解除されます。」

参照: http://msdn.Microsoft.com/en-us/library/ms188782.aspx

6
Eclipses