0

これは非常に長い時間がかかるスクリプトです

USE [r_prod]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:      Drew Borden
-- Create date: 4/16/2009
-- Description: Procedure to populated subdivision extract table
-- =============================================
IF EXISTS(SELECT * FROM sys.procedures WHERE name='sp_extract_subdivision')
BEGIN
    DROP PROCEDURE sp_extract_subdivision
END
GO

CREATE PROCEDURE sp_extract_subdivision 
    @subdivsion_cd char(2) 
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

declare @strap varchar(25)

-- Clear existing record
delete from dbo.subdivision_extract

-- Select list of straps to loop through
declare strapList cursor for
select strap from dbo.parcel where county_cd = @subdivsion_cd

--Loop through straps and populate extract table values
BEGIN TRY
    OPEN strapList
    FETCH NEXT FROM strapList INTO @strap
    WHILE @@FETCH_STATUS = 0
    BEGIN
        IF @strap IS NOT NULL
        BEGIN
            insert into dbo.subdivision_extract (acct_num) values (RTRIM(@strap))
            exec sp_extract_parcel @strap
            exec sp_extract_detail @strap
            exec sp_extract_lnd_c @strap
            exec sp_extract_parcel_flg @strap
            exec sp_extract_owner @strap
            exec sp_extract_mail @strap
            exec sp_extract_legal_ln @strap
            exec sp_extract_site @strap 
            exec sp_extract_condo_unit @strap
            exec sp_extract_personal_x @strap
            exec sp_extract_personal_x_dist @strap
            exec sp_extract_phase_in @strap
            exec sp_extract_p_tax_dist @strap
            exec sp_extract_parcel_rel @strap
            exec sp_extract_entzone @strap
            exec sp_extract_dates @strap
            exec sp_extract_sales @strap
            exec sp_extract_sale_dtl @strap
            exec sp_extract_pchar @strap
            exec sp_extract_protest @strap

        END
        FETCH NEXT FROM strapList INTO @strap
    END
    CLOSE strapList
    DEALLOCATE strapList
END TRY

BEGIN CATCH
    SELECT ERROR_NUMBER() as ErrorNumber, 
            ERROR_MESSAGE() as ErrorMessage,
            ERROR_PROCEDURE() as ExecutingProcedure,
            ERROR_LINE() as LineNumber
    CLOSE strapList
    DEALLOCATE strapList        
END CATCH
END
GO

これをスピードアップする方法はありますか?

4

5 に答える 5

1

ここでの本当の問題は、カーソルを介して20個のストアドプロシージャを順番に呼び出しているという事実です。

私は最初はカーソルが嫌いで、以前のプロジェクトでこれに対する解決策を考え出しました。

カーソルから変数を取得する代わりに、すべてのデータに対して20個のストアドプロシージャを順番に実行できますか?

データの主キーと、処理されたポイントとポイントを示すステータス整数を含む一時テーブルを用意することをお勧めします。次に、すべての行を処理するために、各ストアドプロシージャを呼び出すことができます。

本当に素晴らしい仕事をしたい場合は、各ストアドプロシージャプロセスに一度に5%の行を指定させ、WAITFORを使用して少し休止させてから、すべてのレコードが各ステージで処理されるまでループします。それぞれのプロセス時間が妥当な場合は、ロックを他のプロセスに割り当てることができるため、より重要なプロセスがロックを取得できないためにタイムアウトすることはありません。

どれくらい時間がdelete from dbo.subdivision_extractかかりますか?しばらく時間がかかり、ログが不要な場合(およびテーブルにトリガーがない場合)は、次のように変更してみてください。TRUNCATE TABLE dbo.subdivision_extract

TLDR:すべてのデータを処理するようにストアドプロシージャを再開発すると、20個のストアドプロシージャを1回ずつ呼び出すだけで済みます。

于 2009-11-06T18:04:49.453 に答える
1

これを高速化する最善の方法は、すべての行で呼び出すストアド プロシージャのバージョンを記述して、セット全体に対して実行し、カーソルを完全に捨てることです。それ以外の場合は、カーソルを FORWARD_ONLY として指定することで小さな利点が得られる可能性がありますが、他にできることはあまりありません。

于 2009-11-06T12:22:41.973 に答える
0

このストアドのループごとにいくつかのストアド プロシージャを呼び出しています。他の人が何をしているのかはわかりませんが、いくつかのデータを照会/変更しているようです。保存されているものを 1 つに結合し、ストラップごとにループするのではなく、複数のレコードのブロックでクエリを実行することを検討する必要があります。

于 2009-11-06T12:15:17.523 に答える
0

If you are extracting data to a text file, you owe it to yourself to do it in a set-based manner or at least use SSIS. A cursor running mulitple stored procs for each row is the absolute worst method you can use for this sort of thing. I'd bet you can do this in an SSIS package and take minutes instead of 9 hours.

于 2009-11-06T18:14:25.077 に答える
0

はい、実際には非常に簡単に修正できます。何が遅いかを測定し、遅い部分を最適化します。

あなたが投稿したのは、パフォーマンスに関して可能な限り不透明なT-SQLスクリプトだけです。DELETE、SELECT、INSERT と一連の EXEC を使用したカーソルの反復。問題はこれらのどこにでもある可能性があるため、最善の解決策は、問題がどこにあるかを測定して確認することです。

スクリプトを取得しPRINT GETDATE();、開始時、DELETE の後、最初の FETCH の後、次に各 EXEC の後に a を追加し、1 回の反復を実行します (ループ内の FETCH を削除します)。PRINT 出力を見て、そこから各ステップの実行にかかる時間を推測できます。それらのいずれかが際立っていますか?

Profiler をアタッチし、イベントSP:StmtCompletedを Duration のフィルターで監視します。抽出ループを 1 回繰り返します。デュレーションで最も際立っているステートメントはどれですか?

SSMS で 1 回の反復に対してスクリプトを実行しますが、ツールバーの [実際の実行計画を含める] ボタンをオンにします。結果の実行ショーで、バッチに比べてコストが高いステートメントはどれですか?

問題を絞り込む必要があります。スクリプトを診断することは不可能であるため、このスクリプトで実際に行われる作業はありません。作業を行うために他の手順を呼び出すだけです。このスクリプトによって呼び出されたプロシージャ内の実際の遅いステートメントを特定したら、もう一度投稿し、問題のある正確なステートメントとデータの正確なスキーマ(すべてのインデックス定義を含む) を提供し、特定の問題の解決策を尋ねてください。

理論的には、セット指向の処理はカーソルよりも優れたパフォーマンスを発揮する可能性がありますが、実際には、それらのプロシージャが非常に単純な単一の SELECT でない限り、20 回のストアド プロシージャ実行呼び出しと同じ情報を抽出する単一のステートメントを作成することはおそらく不可能です。

于 2009-11-06T18:31:25.887 に答える