2

いくつかのデータベース テーブルのレコードをコピーおよび削除するために、SQL Enterprise Manager 2000 でジョブをまとめています。大量のコピーと削除のストアド プロシージャを直接実行しましたが、数百万行で実行されている可能性があるため、サーバーがハングします。一度に 100 程度のレコード チャンクでサービスを実行することに興味があったので、サーバーが停止することはありません (これはライブ Web データベースです)。このサービスを 1 晩に 1 回実行したいので、エージェント ジョブに入れました。実際にコピーと削除を行うストアドプロシージャへの呼び出しをループし、各呼び出しの間に「スリープ」してサーバーに追いつく時間を与える方法はありますか? WAITFOR コマンドがあることは知っていますが、これがプロセッサを保持するのか、その間に他のクエリを実行できるのかはわかりません。

ありがとう!

4

3 に答える 3

2

削除を「チャンク化」することは、トランザクション ログ ファイルを肥大化させずに過剰な量のデータを削除するための推奨される方法です。BradC の投稿は、この合理的な例です。

このようなループの管理は、単一のストアド プロシージャ内で行うのが最適です。そのような作業を時間をかけて広めるために、私はまだそれを手順に残しておきます. ループに WAITFOR を挿入すると、同時実行の問題に対処する必要があると思われる場合、削除の各セットの間に「一時停止」が入ります。SQL エージェント ジョブを使用して、プロシージャの開始時期を決定します。特定の時間までに終了する必要がある場合は、それもループに含めます。

このコードに対する私の考えは次のとおりです。

--  NOTE: This is a code sample, I have not tested it
CREATE PROCEDURE ArchiveData

    @StopBy DateTime
    --  Pass in a cutoff time.  If it runs this long, the procedure will stop.
AS

DECLARE @LastBatch  int

SET @LastBatch = 1
--  Initialized to make sure the loop runs at least once


WHILE @LastBatch > 0
 BEGIN

    WAITFOR DELAY '00:00:02'
    --  Set this to your desired delay factor

    DELETE top 1000  --  Or however many per pass are desired
     from SourceTable
    --  Be sure to add a where clause if you don't want to delete everything!

    SET @LastBatch = @@rowcount

    IF getdate() > @StopBy
        SET @LastBatch = 0

 END

RETURN 0

うーん。投稿を読み直すということは、データを削除する前に、まずデータをどこかにコピーすることを意味します。それを行うには、一時テーブルを設定し、ループ内で最初に一時テーブルを切り捨て、次に TOP N 項目の主キーをコピーし、一時テーブルへの結合を介して「アーカイブ」テーブルに挿入します。次に、一時テーブルへの結合を介してソース テーブルも削除します。(単純な削除よりも少し複雑ですよね?)

于 2009-10-21T14:46:05.983 に答える
1

ループ間の待機について心配する必要はありません。SQL サーバーは、メンテナンス ジョブとサーバー上の通常のアクティビティとの間の競合を処理する必要があります。

このような状況で実際に問題を引き起こすのは、削除プロセス全体が 1 つのトランザクション内で一度に発生することです。これにより、データベースのログが爆発し、発生しているように思われる種類の問題が発生する可能性があります。

次のようなループを使用して、扱いやすいチャンクで削除します。

DECLARE @i INT
SET @i = 1

SET ROWCOUNT 10000

WHILE @i > 0
BEGIN
    BEGIN TRAN
        DELETE TOP 1000 FROM dbo.SuperBigTable
        WHERE RowDate < '2009-01-01'
    COMMIT

    SELECT @i = @@ROWCOUNT
END
SET ROWCOUNT 0

コピーに同様のロジックを使用できます。

于 2009-10-21T14:17:59.053 に答える
0

WAITFOR他のプロセスに「試してもらう」ことができます。私はこのテクニックを使って、大規模な DELETE がマシンをロックするのを止めました。WHILE ループを作成し、行のブロックを削除してから、WAITFOR を数秒 (またはそれ以下の適切な時間) 待ちます。

于 2009-10-21T14:15:39.207 に答える