1

我正在遍历我的所有数据库并将结果聚合到聚合数据库中。

在我的循环中,我打电话

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

随着循环的进行,cmdshell 的执行时间越来越长。如果我停止循环并为一个数据库运行单个聚合,它会快速执行。

有什么我可以添加到我的外部 SQL 脚本以使其运行得更快的吗?也许在下一个循环之前提交和释放记录?或者我应该在每个循环之后添加某种暂停?

我想使用外部 SQL 文件,因为它包含许多更新语句,而且对我来说更易于管理。

这是我循环的方式:

更新 dbFoo.dbo.tblBar 设置 Processed = 0
去

存在时(从 dbFoo.dbo.tblBar 中选择 ID,其中已处理 = 0)
    开始

        从 dbFoo.dbo.tblBar 中选择 @aRow = MIN(tblBar.ID)
        从 dbFoo.dbo.tblBar 中选择 @aFoo1 = Foo1,其中 ID = @aRow
        从 dbFoo.dbo.tblBar 中选择 @aFoo2 = Foo2 其中 ID = @aRow
        选择 @aFoo3 = Foo3 从 dbFoo.dbo.tblWhatever WHERE Foo = @aFoo

        执行 RunPreAgg @Foo1 = @aFoo1,@Foo2 = @aFoo2,@Foo3 = @aFoo3,@RetVal = @aRetVal 输出
        选择返回 = @aRetVal

        更新 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 回答