1

すべてのデータベースをループして、結果を集計データベースに集約しています。

私のループでは、私は呼び出します

master.dbo.xp_cmdshell osql C:\whatever.SQL 

ループが進行するにつれて、cmdshellの実行に時間がかかります。ループを停止して、1つのデータベースに対して単一の集計を実行すると、すぐに実行されます。

外部SQLスクリプトを高速化するために追加できるものはありますか?たぶん、次のループの前にレコードをコミットして解放するための何か?または、ループごとに何らかの一時停止を追加する必要がありますか?

外部SQLファイルには多くの更新ステートメントが含まれており、管理しやすいため、外部SQLファイルを使用したいと思います。

ループする方法は次のとおりです。

dbFoo.dbo.tblBarセットを更新しますProcessed=0
行け

WHILE EXISTS(SELECT ID FROM dbFoo.dbo.tblBar WHERE Processed = 0)
    始める

        SELECT @aRow = MIN(tblBar.ID)FROM dbFoo.dbo.tblBar
        SELECT @ aFoo1 = Foo1 FROM dbFoo.dbo.tblBar WHERE ID = @aRow
        SELECT @ aFoo2 = Foo2 FROM dbFoo.dbo.tblBar WHERE ID = @aRow
        SELECT @ aFoo3 = Foo3 FROM dbFoo.dbo.tblWhatever WHERE Foo = @aFoo

        EXEC RunPreAgg @ Foo1 = @ aFoo1、@ Foo2 = @ aFoo2、@ Foo3 = @ aFoo3、@ RetVal = @aRetVal OUTPUT
        SELECT戻り値=@aRetVal

        UPDATE dbFoo.dbo.tblBar SET Processed = 1 WHERE ID = @aRow
    終わり

次に、RunPreAggストアドプロシージャは基本的にこれを行います。

if db_id('db' + @Foo1 + '_' + @Foo2) is not null  
    BEGIN
        --This bat file creates the SQL File
        select @sql = 'master.dbo.xp_cmdshell '''+@path+'wwwRunPreAgg.bat ' + @Foo1 + ' ' + @Foo2 + ' ' + @Foo3 + ''''
        exec( @sql )

        --execute
        select @sql = 'master.dbo.xp_cmdshell ''osql -E -o '+@path+'output\tmp'+@Foo1+'_'+@Foo2+'.txt -i '+@path+'tmp' + @Foo1 + '.SQL'''
        exec( @sql )

        --This erases the SQL File
        select @sql = 'master.dbo.xp_cmdshell '''+@path+'wwwCleanup.bat ' + @Foo1 + ' ' + @Foo2 + ''''
        exec( @sql )

        Set @retval = 'Done!'
    END
ELSE
    BEGIN
        Set @retval = 'Err: No DataBase'
    END 

変数名は、無実を保護するために変更されます。コードは正常に機能します。最適化する必要があります。

4

1 に答える 1

0

問題を引き起こしているのがループのパフォーマンスである場合は、選択の数を減らしてみてください。通常、私はカーソルが嫌いですが、あなたのループはカーソルの恩恵を受けるかもしれません。ループに必要なすべての値をメモリに選択し、ループごとに3つまたは4つの選択を実行せずにそれらの値をループできます(もちろん、パフォーマンスヒットがRunPreAgg SP内で発生している場合、これは役に立ちません) :

DECLARE cFoos CURSOR FOR 
    SELECT tblBar.ID, tblBar.Foo1, tblBar.Foo2, tblWhatever.Foo3
    FROM dbFoo.dbo.tblBar
        INNER JOIN dbFoo.dbo.tblWhatever
            ON tblWhatever.Foo = tblBar.Foo
    WHERE tblBar.Processed = 0;

OPEN cFoos;
FETCH NEXT FROM cFoos INTO @aRow, @aFoo1, @aFoo2, @aFoo3;

WHILE @@FETCH_STATUS = 0
BEGIN
    EXEC RunPreAgg @Foo1 = @aFoo1, @Foo2 = @aFoo2, @Foo3 = @aFoo3, @RetVal = @aRetVal OUTPUT
    SELECT returning = @aRetVal

    UPDATE dbFoo.dbo.tblBar SET Processed = 1 WHERE ID = @aRow

   FETCH NEXT FROM cFoos INTO @aRow, @Foo1, @Foo2, @Foo3;
END

CLOSE cFoos;
DEALLOCATE cFoos;
于 2010-08-25T23:09:39.723 に答える