2010-08-25 60 views
1

我正在循環所有我的數據庫和聚合結果到聚合數據庫。tsql循環與外部查詢

在我的循環我叫

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

隨着循環的進行,CMDSHELL需要更長的時間才能執行。如果我停止循環併爲一個數據庫運行單個聚合,它會很快執行。

有什麼我可以添加到我的外部SQL腳本,使其運行速度更快?也許在下一個循環之前提交併釋放記錄?或者我應該在每個循環之後添加某種停頓?

我想使用外部SQL文件,因爲它包含許多更新語句,對我來說更易於管理。

下面是我的循環:

 
Update dbFoo.dbo.tblBar set Processed = 0 
Go 

WHILE EXISTS (SELECT ID FROM dbFoo.dbo.tblBar WHERE Processed = 0) 
    BEGIN 

     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 returning = @aRetVal 

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

然後RunPreAgg存儲過程基本上做到這一點:

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

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

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

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

變量名稱更改爲保護無辜者。代碼工作正常,我只需要優化。

+0

也許你應該發表你的循環如何通過數據庫? – DForck42 2010-08-25 21:33:52

+0

好吧,我添加了我的循環代碼 – shitburg 2010-08-25 22:06:25

回答

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; 
+0

我覺得自己像一個doofus ...原來是RunPreAgg,我錯過了各種索引。我將使用循環代碼進一步優化。謝謝 – shitburg 2010-08-25 23:53:35