2

あるテーブルから別のテーブルに大量のデータをコピーしたいのですが、ストアド プロシージャでカーソルを使用して同じことを行いました。ハングしました。データをより高速にコピーする方法を提案してください。私の SP は次のとおりです。

--exec uds_shop

--select * from CMA_UDS.dbo.Dim_Shop
--select * from UDS.dbo.Dim_Shop
--delete from CMA_UDS.dbo.Dim_Shop

alter procedure uds_shop
as
begin
declare @dwkeyshop int
declare @shopdb int
declare @shopid int
declare @shopname nvarchar(60)
declare @shoptrade int
declare @dwkeytradecat int
declare @recordowner nvarchar(20)
declare @LogMessage varchar(600)

Exec CreateLog 'Starting Process', 1 

DECLARE cur_shop CURSOR FOR
    select 
    DW_Key_Shop,Shop_ID,Shop_Name,Trade_Sub_Category_Code,DW_Key_Source_DB,DW_Key_Trade_Category,Record_Owner
    from 
    UDS.dbo.Dim_Shop 

    OPEN  cur_shop
    FETCH NEXT FROM cur_shop INTO @dwkeyshop,@shopid,@shopname,@shoptrade, @shopdb ,@dwkeytradecat,@recordowner
    WHILE @@FETCH_STATUS = 0 
    BEGIN 
    Set @LogMessage = ''
    Set @LogMessage = 'Records insertion/updation start date and time : ''' + Convert(varchar(19), GetDate()) + ''''            

    if (isnull(@dwkeyshop, '') <> '')
        begin 
        if not exists (select crmshop.DW_Key_Shop from CMA_UDS.dbo.Dim_Shop as crmshop where (convert(varchar,crmshop.DW_Key_Shop)+CONVERT(varchar,crmshop.DW_Key_Source_DB)) = convert(varchar,(CONVERT(varchar, @dwkeyshop) + CONVERT(varchar, @shopdb))) )
        begin
        Set @LogMessage = Ltrim(Rtrim(@LogMessage)) + ' ' + 'Record for shop table is inserting...'         
                insert into 
                 CMA_UDS.dbo.Dim_Shop
                (DW_Key_Shop,DW_Key_Source_DB,DW_Key_Trade_Category,Record_Owner,Shop_ID,Shop_Name,Trade_Sub_Category_Code)
                values
                (@dwkeyshop,@shopdb,@dwkeytradecat,@recordowner,@shopid,@shopname,@shoptrade)
        Set @LogMessage = Ltrim(Rtrim(@LogMessage)) + ' ' + 'Record successfully inserted in shop table for shop Id : ' + Convert(varchar, @shopid) 

            end
            else

            begin 
             Set @LogMessage = Ltrim(Rtrim(@LogMessage)) + ' ' + 'Record for Shop table is updating...' 
             update 
             CMA_UDS.dbo.Dim_Shop
             set DW_Key_Trade_Category=@dwkeytradecat,
             Record_Owner=@recordowner,
             Shop_ID=@shopid,Shop_Name=@shopname,Trade_Sub_Category_Code=@shoptrade

             where       
                DW_Key_Shop=@dwkeyshop and DW_Key_Source_DB=@shopdb     
             Set @LogMessage = Ltrim(Rtrim(@LogMessage)) + ' ' + 'Record successfully updated for shop Id : ' + Convert(varchar, @shopid)
            end
        end
        Exec CreateLog @LogMessage, 0
        FETCH NEXT FROM cur_shop INTO @dwkeyshop,@shopid,@shopname,@shoptrade, @shopdb ,@dwkeytradecat,@recordowner
    end
    CLOSE cur_shop 
    DEALLOCATE cur_shop
End
4

4 に答える 4

5

と同じスキーマtargetTableを持っていると仮定します...destinationTable

INSERT INTO targetTable t
SELECT * FROM destinationTable d
WHERE someCriteria

他に方法がない場合 (まれ) を除いて、カーソルの使用は避けてください。

このWHERE句を使用して、重複するレコードを除外できます。

ID 列がある場合は、ID 列を含まない明示的な列リストを使用します。

制約を無効にしてインデックスを削除することもできますが、後でそれらを置き換える (そして制約がチェックされていることを確認する) ことができます。

SQL Server 2008 (以降) を使用している場合は、MERGEステートメントを使用できます。

于 2012-09-09T06:44:45.007 に答える
1

私の個人的な経験から、巨大なデータをあるテーブルから別のテーブルに (同様の制約で) コピーするときは、データがコピーされるテーブルの制約を削除します。コピーが完了したら、すべての拘束を再度元に戻します。

私の場合、コピー時間を 7 時間から 30 分に短縮できました (6 つの制約を持つ 1 億レコード)。

于 2012-09-09T06:44:12.947 に答える
0

カーソルは非常に遅いことで有名であり、非常に大きなデータセットでは RAM が問題になり始める可能性があります。

各反復でかなりのログを記録しているように見えるので、カーソルで立ち往生している可能性がありますが、代わりに、フットプリントを小さく保つことができるように、ジョブを複数の呼び出しに分割する方法を探します.

自動採番列がある場合は、プロシージャに「@startIdx bigint」を追加し、「TOP 1000」「WHERE [autonumberFeild] <= @startIdx Order by [autonumberFeild]」を取るようにカーソル ステートメントを再定義します。次に、次のような新しいストアド プロシージャを作成します。

DECLARE @startIdx bigint = 0
WHILE select COUNT(*) FROM <sourceTable> > @startIdx
BEGIN
    EXEC <your stored procedure> @startIdx
END
SET @startIdx = @startIdx + 1000

また、データベース ファイルが自動拡張に設定されていること、および自動拡張が大幅に増加するように設定されていることを確認してください。これにより、データ ファイルの拡張にすべての時間を費やさなくて済みます。

于 2012-09-09T07:00:31.750 に答える
0
INSERT INTO targetTable 
SELECT * FROM destinationTable 
WHERE someCriteria (based on Criteria you can copy/move the records)
于 2013-09-11T12:28:28.793 に答える