5

ストアド プロシージャで囲まれたカーソルの実行に問題があるわけではありません。しかし、私は同じことを達成するためのより効率的な方法を見つけたいと思っています。

ここに行きます。

ストアド プロシージャ: RawFeed.sql(5 分ごとに実行)

Set @GetATM = Cursor For
        Select DeviceCode,ReceivedOn
        From RawStatusFeed
        Where CRWR=2 AND Processed=0
        Order By ReceivedOn Desc
    Open @GetATM
    Fetch Next
    From @GetATM Into @ATM,@ReceivedOn
    While @@FETCH_STATUS = 0
        Begin
            Set @RawFeed=@ATM+' '+Convert(VarChar,@ReceivedOn,121)+' '+'002307'+' '+@ATM+' : Card Reader/Writer - FAULTY '
            Exec usp_pushRawDataAndProcess 1,@RawFeed
            Fetch Next
            From @GetATM Into @ATM,@ReceivedOn
        End
Set @GetATM = Cursor For
        Select DeviceCode,ReceivedOn
        From RawStatusFeed
        Where CRWR=0 AND Processed=0
        Order By ReceivedOn Desc
    Open @GetATM
    Fetch Next
    From @GetATM Into @ATM,@ReceivedOn
    While @@FETCH_STATUS = 0
        Begin
            Set @RawFeed=@ATM+' '+Convert(Varchar,@ReceivedOn,121)+' '+'002222'+' '+@ATM+' : Card Reader/Writer - OK '
            Exec usp_pushRawDataAndProcess 1,@RawFeed
            Fetch Next
            From @GetATM Into @ATM,@ReceivedOn
        End

同様に、条件パラメーターと変数で囲まれた文字列SETが異なるステートメントがさらに 10 個あります。WHERE@RawFeed

取得した行ごとに、その特定の行で別のストアド プロシージャを実行します。

私の質問は

カーソルを使用せずに同じことを達成するより良い方法はありますか?

変数 @ストアド プロシージャへの入力となるRawFeed次のものが含まれます。これで文字列全体が分割され、いくつかのテーブルのような操作が行われます。stringusp_pushRawDataAndProcessINSERT,UPDATE,DELETE

1 つ以上の文字列を処理することはできませんusp_pushRawDataAndProcess

NMAAO226 2012-09-22 16:10:06.123 002073 NMAAO226 : Journal Printer - OK 
WMUAO485 2012-09-22 16:10:06.123 002222 WMUAO485 : Card Reader/Writer - OK 
4

4 に答える 4

3

パフォーマンスが遅いため、私は常にカーソルが嫌いでした。しかし、さまざまな種類のカーソルを完全には理解していないことがわかりました。また、場合によっては、カーソルが実行可能なソリューションであることがわかりました。

一度に 1 行ずつ処理することによってのみ解決できるビジネス上の問題がある場合は、カーソルが適しています。

したがって、カーソルのパフォーマンスを向上させるには、使用しているカーソルの種類を変更してください。私が知らなかったのは、宣言しているカーソルのタイプを指定しない場合、デフォルトで動的楽観タイプを取得することでした。これは、フードの下で多くの作業を行っているため、パフォーマンスが最も遅いタイプです。 . ただし、カーソルを別のタイプ (静的カーソルなど) として宣言することにより、非常に優れたパフォーマンスが得られます。

詳細な説明については、次の記事を参照してください。

カーソルについての真実: パート I

カーソルについての真実: パート II

カーソルについての真実: パート III

カーソルに対する最大の短所はパフォーマンスだと思いますが、セットベースのアプローチでタスクを配置しないと、おそらく 2 番目にランクされます。3 つ目は、タスクの読みやすさとレイアウトです。タスクには通常、役立つコメントがあまりないためです。

私が見つけたカーソルに代わる最良の方法は、ロジックを作り直してセットベースのアプローチを取ることです。

SQL Server は、セット ベースのアプローチを実行するように最適化されています。たとえばテーブルの結合のように、データの結果セットを返すクエリを記述しますが、SQL Server 実行エンジンは、使用する結合 (マージ結合、ネストされたループ結合、またはハッシュ結合) を決定します。SQL Server は、関係する列、データ ボリューム、インデックス構造、および関係する列の値のセットに基づいて、最適な結合アルゴリズムを決定します。そのため、一般的には、プロシージャル カーソル アプローチよりもパフォーマンスの点で最良のアプローチです。

カーソルとその回避方法に関する記事を次に示します。 また、カーソルの代替手段についても説明します。

于 2013-08-21T14:34:09.933 に答える
3

SQL Server は、他のリレーショナル データベースと同様に、一連のデータを処理するように設計されており、それを得意としています。

データベースは、最適化のすべての機会がクエリ処理エンジンから隠されている手続き型コードが苦手です。

独自のリクエスト文字列を保存するために使用RawStatusFeedし、それらのリストを 1 つずつ処理することは、データベース コードにとって非効率的です。これにより、クライアントにとって挿入が非常に高速になる可能性があり、これは非常に重要かもしれませんが、代償が伴います。

リクエスト文字列を挿入時に分割するか、特殊な SP 呼び出しを介して挿入する前に分割すると、文字列のリストではなく、必要な変更を何らかの中間リレーショナル モデルに格納できます。その後、場合によっては、ストアド プロシージャを 1 回呼び出すだけで、すべての変更を一度に処理できます。確かに、そのストアド プロシージャに複数のクエリ ステートメントを含めることはおそらく理にかなっています。ただし、適切なインデックスと統計があれば、クエリ処理エンジンは、この新しいストアド プロシージャの効率的な実行計画を立てることができます。

これを実現する方法の正確な詳細は、RawStatusFeedテーブルの正確な詳細と の実装によって異なりますusp_pushRawDataAndProcess。これは書き直しのように見えますが、DeviceCodeコラムがそれほど複雑であるとは思いません。


したがって、短い答えは確かにイエスですが、詳細を知る必要がありusp_pushRawDataAndProcessます。

SPの署名がusp_pushRawDataAndProcessボトルネックになっています。


変更することができずusp_pushRawDataAndProcess、セットベースの代替案を作成しない場合は、ボトルネックで立ち往生しています.

したがって、ボトルネックを取り除くのではなく、別の方法を取ることができます。データをフィードするために、ボトルネックの同時インスタンスを増やしてみませんか。

SQL Server 2005 以降を使用している場合は、いくつかの CLR を使用して多数のインスタンスをusp_pushRawDataAndProcess並行して実行できます。

これは、以前に同様のことを行うために使用したプロジェクトへのリンクです。

于 2012-09-26T11:38:26.763 に答える
0

SQL サーバーでの CURSOR の代替

1.While loop
2.Recursive CTE
于 2012-09-26T11:11:48.123 に答える