8

一般に、ストアド プロシージャでのカーソルの使用は可能な限り避けるべきであると認められています (セット ベースのロジックなどに置き換えます)。一部のデータを反復処理する必要があり、読み取り専用の方法で実行できる場合、早送り (読み取り専用転送) カーソルは while ループよりも多かれ少なかれ非効率的ですか? 私の調査によると、カーソルオプションは一般的に高速で、読み取りと CPU 時間の使用量が少ないようです。大規模なテストは行っていませんが、これは他の人が見つけたものですか? このタイプ (早送り) のカーソルは、追加のオーバーヘッドや、私が知らない高価なリソースを運ぶのでしょうか。

セットベースのアプローチが利用可能な場合にカーソルの使用を避けること、および更新可能なカーソルなどを使用することについて、カーソルを使用しないことについてのすべての話です.

ありがとう

4

9 に答える 9

19

早送りカーソルにはSQLServer2005でいくつかの最適化がありますが、パフォーマンスの点でセットベースのクエリに近いというわけではありません。カーソルロジックをセットベースのクエリで置き換えることができない状況はほとんどありません。ローカル変数を埋めるために実行を中断し続ける必要があるという事実もあり、カーソルは常に本質的に遅くなります。

ここにいくつかの参考資料があります。これは、この問題を調査する場合にのみ氷山の一角になります。

http://www.code-magazine.com/Article.aspx?quickid=060113

http://dataeducation.com/re-inventing-the-recursive-cte/

于 2008-09-01T21:20:24.893 に答える
2

「FAST FORWARD よりも高速なカーソルが必要な場合は、STATIC カーソルを使用してください。FAST FORWARD よりも高速です。極端に高速ではありませんが、違いを生むことができます。」

そんなに早くない!Microsoft によると、「通常、これらの変換が行われると、カーソル タイプは「より高価な」カーソル タイプに劣化します。一般に、(FAST) FORWARD-ONLY カーソルが最もパフォーマンスが高く、次に DYNAMIC、KEYSET、最後に STATIC が続きます。一般的にパフォーマンスが最も低いです。」

から: http://blogs.msdn.com/b/mssqlisv/archive/2006/06/23/644493.aspx

于 2010-07-13T17:06:42.770 に答える
2

この回答は、これまでの回答を統合することを望んでいます。

1)可能であれば、クエリにセットベースのロジックを使用します。つまり、適切な句またはネストされたクエリを使用してSELECT、 , INSERT,UPDATEまたはのみを使用してください。これらはほとんどの場合高速です。DELETEFROM

2) 上記が不可能な場合は、SQL Server 2005 以降でFAST FORWARDはカーソルが効率的でパフォーマンスが高く、while ループよりも優先して使用する必要があります。

于 2009-01-20T13:57:13.610 に答える
2

ほとんどの場合、カーソルを避けることができますが、必要な場合もあります。

FAST_FORWARD は DYNAMIC ... FORWARD_ONLY であり、STATIC カーソルで使用できることに注意してください。

ハロウィーンの問題でそれを使ってみて、何が起こるか見てみましょう!!!

IF OBJECT_ID('Funcionarios') IS NOT NULL
DROP TABLE Funcionarios
GO

CREATE TABLE Funcionarios(ID          Int IDENTITY(1,1) PRIMARY KEY,
                          ContactName Char(7000),
                          Salario     Numeric(18,2));
GO

INSERT INTO Funcionarios(ContactName, Salario) VALUES('Fabiano', 1900)
INSERT INTO Funcionarios(ContactName, Salario) VALUES('Luciano',2050)
INSERT INTO Funcionarios(ContactName, Salario) VALUES('Gilberto', 2070)
INSERT INTO Funcionarios(ContactName, Salario) VALUES('Ivan', 2090)
GO

CREATE NONCLUSTERED INDEX ix_Salario ON Funcionarios(Salario)
GO

-- Halloween problem, will update all rows until then reach 3000 !!!
UPDATE Funcionarios SET Salario = Salario * 1.1
  FROM Funcionarios WITH(index=ix_Salario)
 WHERE Salario < 3000
GO

-- Simulate here with all different CURSOR declarations
-- DYNAMIC update the rows until all of then reach 3000
-- FAST_FORWARD update the rows until all of then reach 3000
-- STATIC update the rows only one time. 

BEGIN TRAN
DECLARE @ID INT
DECLARE TMP_Cursor CURSOR DYNAMIC 
--DECLARE TMP_Cursor CURSOR FAST_FORWARD
--DECLARE TMP_Cursor CURSOR STATIC READ_ONLY FORWARD_ONLY
    FOR SELECT ID 
          FROM Funcionarios WITH(index=ix_Salario)
         WHERE Salario < 3000

OPEN TMP_Cursor

FETCH NEXT FROM TMP_Cursor INTO @ID

WHILE @@FETCH_STATUS = 0
BEGIN
  SELECT * FROM Funcionarios WITH(index=ix_Salario)

  UPDATE Funcionarios SET Salario = Salario * 1.1 
   WHERE ID = @ID

  FETCH NEXT FROM TMP_Cursor INTO @ID
END

CLOSE TMP_Cursor
DEALLOCATE TMP_Cursor

SELECT * FROM Funcionarios

ROLLBACK TRAN
GO
于 2014-12-08T13:31:55.107 に答える
1

一般に、単純な while ループよりも書き込みが難しいため、人々はカーソルを避けますが、while ループは、テーブルから一時的またはその他の方法で常にデータを選択するため、コストがかかる可能性があります。

読み取り専用の早送りであるカーソルを使用すると、データはメモリに保持され、ループ用に特別に設計されています。

この記事では、平均的なカーソルが while ループよりも 50 倍速く実行されることを強調しています。

于 2008-08-31T22:16:31.567 に答える
1

マイルの最初の質問に答えるには...

早送り、読み取り専用、静的カーソル (親しみを込めて「Fire Hose Cursor」として知られています) は、通常、同等の一時テーブルおよび While ループと同じかそれ以上の速さです。舞台裏で少し最適化されています。

Eric Z. Beard がこのスレッドに投稿した内容に追加し、さらに次の質問に答えるには...

「セットベースのアプローチが利用可能な場合にカーソルの使用を避けること、および更新可能なカーソルなどを使用することについて、カーソルを使用しないことについてのすべての話はありますか?」

はい。ほとんどのカーソルと同じことを行う適切なセットベースのコードを記述するのに必要な時間とコードはほとんどありませんが、ほとんどのカーソルと同じことを行います。さらに、使用するリソースがはるかに少なくなるという利点があり、通常はカーソルや While ループよりもはるかに高速に実行されます。一般的に言えば、特定の管理タスクを除いて、適切に記述されたセットベースのコードを優先して、管理タスクを実際に回避する必要があります。もちろん、すべての「ルール」には例外がありますが、カーソル、While ループ、およびその他の形式の RBAR の場合、ほとんどの人はすべての指を使わなくても片手で例外を数えることができます。;-)

「隠れたRBAR」という概念もあります。これは、セットベースのように見えますが、実際にはそうではないコードです。このタイプの「セットベース」コードが、特定の人々が RBAR メソッドを採用し、「OK」と言う理由です。たとえば、集計 (SUM) 相関サブクエリと不等式を使用して現在の合計の問題を解決し、現在の合計を構築することは、私の本では実際にはセットベースではありません。代わりに、計算された各行に対して、N * (N + 1) / 2 の割合で他の多くの行に繰り返し「接触」する必要があるため、ステロイドの RBAR です。これは「三角結合」として知られており、完全なデカルト結合 (クロス結合または「四角結合」) の少なくとも半分は悪くなります。

MS は SQL Server 2005 以降、カーソルの動作方法にいくつかの改善を加えましたが、「高速カーソル」という用語は、適切に記述されたセットベースのコードと比較すると、依然として矛盾しています。それはオラクルにも当てはまります。私は過去 3 年間、Oracle で働いていましたが、私の仕事は既存のコードのパフォーマンスを改善することでした。Cursors をセットベースのコードに変換したときに、本当に大幅な改善のほとんどが実現しました。以前は実行に 4 ~ 8 時間かかっていた多くのジョブが、数分、場合によっては数秒に短縮されました。

于 2012-12-30T22:47:28.837 に答える
-1

SQL Serverでカーソルを回避する「ベストプラクティス」は、SQLServer2000以前のバージョンにまでさかのぼります。SQL 2005でのエンジンの書き直しは、特に早送りオプションの導入により、カーソルの問題に関連する問題のほとんどに対処しました。カーソルはセットベースよりも必ずしも悪くはなく、Oracle PL / SQL(LOOP)で広く使用されています。

あなたが参照する「一般的に受け入れられている」有効でしたが、現在は古くて正しくありません-早送りカーソルがアドバタイズされたとおりに動作し、実行されると仮定してください。SQL2005以降に基づいて、いくつかのテストと調査を行います。

于 2008-09-01T21:05:26.830 に答える
-2

FAST FORWARD よりも高速なカーソルが必要な場合は、STATIC カーソルを使用します。FAST FORWARD よりも高速です。極端に速くはありませんが、違いを生むことができます。

于 2008-09-18T09:11:24.377 に答える