13

SQL Server の開発者は、一部の状況を除いて、カーソルは悪い習慣だと考えています。彼らは、Cursors が SQL エンジンを最適に使用していないと考えています。SQL エンジンは手続き型の構造であり、RDBMS のセット ベースの概念を無効にするからです。

ただし、Oracle の開発者は、Cursors を推奨していないようです。Oracle の DML ステートメント自体は暗黙カーソルです。

このアプローチの違いはなぜですか?これら 2 つの製品の製造方法によるものですか、それともこのアドバイスは両方の製品に適用されますか?

4

5 に答える 5

22

Oracleカーソルの問題点は、との両方で頻繁に乱用されることMS SQLです。

カーソルは、行ごとに取得できる安定した結果セットを保持するためのものです。これらは、クエリの実行時に暗黙的に作成され、終了時に閉じられます。

もちろん、そのような結果セットを保持するには、いくつかのリソースが必要です: lockslatchesmemory、さらにはdisk space.

これらのリソースの解放が早ければ早いほど良いです。

カーソルを開いたままにしておくことは、冷蔵庫のドアを開けたままにしておくようなものです

必要なく何時間もそれをするわけではありませんが、決して冷蔵庫を開けてはいけないという意味ではありません。

つまり、次のことを意味します。

  • 結果を行ごとに取得して合計するのではなく、代わりにSQL'sを呼び出しますSUM
  • rownum <= 10クエリ全体を実行してカーソルから最初の結果を取得するのではなく、クエリに条件を追加します

など

に関しては、プロシージャ内でカーソルを処理するには、カーソルからクエリの結果を取得するたびに発生Oracleする悪名高いことが必要です。SQL/PLSQL context switchSQL

これには、スレッド間で大量のデータを渡し、スレッドを同期することが含まれます。

これは で最も苛立たしいことの 1 つですOracle

その動作のあまり明白でない結果の 1 つは、可能であれば Oracle でのトリガーを避ける必要があることです。

トリガーを作成してDML関数を呼び出すことは、カーソルを開いて更新された行を選択し、このカーソルの各行のトリガー コードを呼び出すことと同じです。

DMLトリガーが存在するだけで (空のトリガーであっても)、操作が遅くなる可能性があり10 timesます。

上のテスト スクリプト10g:

SQL> CREATE TABLE trigger_test (id INT NOT NULL)
  2  /

Table created

Executed in 0,031 seconds
SQL> INSERT
  2  INTO   trigger_test
  3  SELECT level
  4  FROM   dual
  5  CONNECT BY
  6     level <= 1000000
  7  /

1000000 rows inserted

Executed in 1,469 seconds
SQL> COMMIT
  2  /

Commit complete

Executed in 0 seconds
SQL> TRUNCATE TABLE trigger_test
  2  /

Table truncated

Executed in 3 seconds
SQL> CREATE TRIGGER trg_test_ai
  2  AFTER INSERT
  3  ON trigger_test
  4  FOR EACH ROW
  5  BEGIN
  6     NULL;
  7  END;
  8  /

Trigger created

Executed in 0,094 seconds
SQL> INSERT
  2  INTO   trigger_test
  3  SELECT level
  4  FROM   dual
  5  CONNECT BY
  6     level <= 1000000
  7  /

1000000 rows inserted

Executed in 17,578 seconds

1.47トリガーなしの17.57秒、何もしない空のトリガーの秒。

于 2009-04-14T12:47:10.940 に答える
14

MSDNから: カーソルの実装

カーソルを使用すると、デフォルトの結果セットを使用するよりも効率が低下します。デフォルトの結果セットでは、クライアントからサーバーに送信される唯一のパケットは、実行するステートメントを含むパケットです。サーバー カーソルを使用する場合、各 FETCH ステートメントをクライアントからサーバーに送信する必要があります。サーバーでは、ステートメントを解析して実行プランにコンパイルする必要があります。

Transact-SQL ステートメントが、クライアント アプリケーションで使用可能なメモリにキャッシュできる比較的小さな結果セットを返し、ステートメントを実行する前に結果セット全体を取得する必要があることがわかっている場合は、既定の結果セットを使用します。アプリケーションの機能をサポートするためにカーソル操作が必要な場合、または結果セットの一部のみが取得される可能性が高い場合にのみ、サーバー カーソルを使用してください。

私は Oracle の DBA ではないので、実装がどのように異なるのかを実際に話すことはできません。ただし、プログラミングの観点からは、セット ベースの操作は、ほとんどの場合、カーソルで結果を処理するよりも高速です。

于 2009-04-13T06:42:01.623 に答える
1

誰かがもっと詳しく説明できると思いますが、基本的には SQL サーバーのカーソルが遅いということになります。

于 2009-04-13T06:30:34.130 に答える