2017-06-01 2 views
0

Ich habe eine dynamische Abfrage, um Indizes und Statistiken für alle Verbindungsserver neu zu erstellen, die an unseren zentralen SQL Server angeschlossen sind und in der Liste enthalten sind. Es funktioniert gut, aber führt die Anweisungen in Serie aus, wenn sie viel schneller abgeschlossen werden können, wenn sie auf separaten Spids ausgeführt werden, da es die Remote-Server sind, die die Arbeit ausführen. Gibt es eine Möglichkeit, das Skript so zu ändern, dass sie parallel ausgeführt werden können, statt darauf zu warten, dass alle nacheinander ausgeführt werden?So führen Sie eine dynamische Abfrage über mehrere Threads aus

WITH TillNames as (select * from (values 
('[DEVELOPERSVR]', '100', 'AD01'), 
('[TESTSVR1]', '100', 'AD02'), 
('[TESTSVR2]', '100', 'AD03'), 
('[TESTSVR3]', '100', 'AD04') -- and two hundred more. 
) a ([TillName], [Branch], [TillDesc])) -- Branch and Till Desc used for other purposes, removed here 
select * INTO #tills from TillNames 

declare @TillName as nvarchar(20), @Branch as nvarchar(5), @TillDesc as nvarchar(100) 
declare @sql as nvarchar(max) 

declare mycursor cursor for Select [TillName], [Branch], [TillDesc] from #tills 
declare @query as nvarchar(max) 

open mycursor 
fetch next from mycursor into @TillName, @Branch, @TillDesc 
while @@FETCH_STATUS=0 
    BEGIN 
    set @sql = 'USE [LOCALDB] 
       Declare  @TBname nvarchar(255), @SQL nvarchar(max) 
       select @TBname = min(TABLE_NAME) from INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE=''''BASE TABLE'''' 
       while @TBname is not null 
        BEGIN 
         begin try 
          set @SQL=''''ALTER INDEX ALL ON ['''' + @TBname + ''''] REBUILD; '''' 
          SET @SQL = @SQL + N''''UPDATE STATISTICS ['''' + @TBname + ''''] WITH FULLSCAN; '''' 
          EXEC SP_EXECUTESQL @SQL 
         end try 
         begin catch 
         print ''''DID NOT WORK: '''' + @SQL 
         end catch 
         select @TBname = min(TABLE_NAME) from INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE=''''BASE TABLE'''' and TABLE_NAME > @TBname   
        END' 
    set @query = N'EXEC (''' + @sql + N''') AT ' + @TillName 
    exec (@query) 
    fetch next from mycursor into @TillName, @Branch, @TillDesc 
    END 
close mycursor 
deallocate mycursor 
drop table #tills 

Antwort

2

Die einfachste, wenn auch kludgey Art, wie ich glaube, aus kann, ist ein SQL Server-Agent-Auftrag für jeden Index wieder aufbauen zu erstellen, dann jeden Job abfeuern eines After-andere.

Hey, ich sagte, es war klugdy! :)

Der bessere Weg, der eine erhebliche Menge an Code beteiligt wäre die Verwendung des Sql Server Service Broker. Sie können aber zusammen ein grundlegendes Framework ziemlich schnell, aber wenn Sie wollen, dass es belastbar ist, dann werden Sie einige Zeit darauf verbringen wollen. Eine andere Methode, die etwas dazwischen sein kann, aber das Schreiben von Code in eine .Net-Sprache wie C# beinhaltet, wäre das Schreiben einer Prozedur, die asynchrone Aufrufe auslöst, obwohl Sie möglicherweise darauf achten müssen, dafür Ressourcen zu verwenden.

Ihre beste ‚externe aber interne‘ Option wäre der Index in einem SSIS-Paket neu erstellt und das von Ihrem Skript aufrufen zu setzen, entweder als SQL-Agent-Job oder direkt aufgerufen,

TL; DR.: Sql Server selbst bietet keine systemeigene Methode zum Ausführen asynchroner Abfragen über T-SQL.

+0

Danke, Rachel. Jede Neuerstellung als Job ist ein letzter Ausweg, da wir mehr als 200 benötigen ... aber ein einzelnes TSQL-Skript könnte 200 Jobs nach einem sofortigen Zeitplan erstellen, die sich bei Beendigung selbst löschen. Ist das eine Möglichkeit, asynchrone Abfragen auszuführen? – cloudsafe

+0

Ja, es ist und würde mehr Berechtigungen erfordern, kaufen ja, das ist eine Möglichkeit. Alles hängt davon ab, wie viel Code Sie erstellen möchten! Außerdem können Sie einen laufenden Job möglicherweise nicht löschen, sodass Sie wahrscheinlich einen "festen" Job für die Haushaltsführung aufrufen müssen, der nach abgeschlossenen "temp" -Aufträgen sucht und diese entfernt. –

Verwandte Themen