it-swarm-eu.dev

Wie verkleinere ich alle Dateien schnell für alle Datenbanken?

Wie kann ich in SQL Server (in diesem Fall 2008) schnell alle Dateien, sowohl das Protokoll als auch die Daten, für alle Datenbanken einer Instanz verkleinern? Ich könnte durch SSMS gehen und mit der rechten Maustaste auf jedes klicken und Aufgaben -> Verkleinern wählen, aber ich suche etwas schnelleres.

Ich habe einige "Datenbank erstellen" -Skripte per Skript erstellt und vergessen, dass sie standardmäßig übergroße Größen haben und nicht so viel Speicherplatz für diese Dateien in diesem Projekt benötigen.

47
jcolebrand

Wenn Sie in der GUI "Aufgaben -> Verkleinern" ausführen, wird hinter den Kulissen ein Befehl DBCC SHRINKDATABASE Ausgegeben. Versuch es. Wenn das Dialogfeld angezeigt wird, klicken Sie nicht auf die Schaltfläche "OK". Klicken Sie stattdessen auf die Schaltfläche "Skript". Sie sehen den Befehl in einem Abfragefenster. Kombinieren Sie dies mit einer Abfrage in sys.databases (lassen Sie master und msdb weg), und Sie können ein Skript erstellen, um alle Datenbanken zu verkleinern.

Zum Beispiel (aus dem Kommentar von jcolebrand):

SELECT 
      'USE [' + d.name + N']' + CHAR(13) + CHAR(10) 
    + 'DBCC SHRINKFILE (N''' + mf.name + N''' , 0, TRUNCATEONLY)' 
    + CHAR(13) + CHAR(10) + CHAR(13) + CHAR(10) 
FROM 
         sys.master_files mf 
    JOIN sys.databases d 
        ON mf.database_id = d.database_id 
WHERE d.database_id > 4;

Kopieren Sie die Ausgabe dieser Abfrage und führen Sie sie aus, um alle Ihre Dateien zu verkleinern.

59
Larry Coleman

Wie wäre es mit einer einzelnen Zeile der SQL-Anweisung?

Bitte lesen Sie diesen sehr interessanten Blog-Beitrag, bevor Sie die folgende SQL-Anweisung ausführen.

EXEC sp_MSForEachDB 'DBCC SHRINKDATABASE (''?'' , 0)'
22
CoderHawk

DBCC SHRINKDB (und sein Cousin SHRINKFILE) sind extrem langsam, da in diesem Code viele Single-Threaded-Ausführungen stattfinden.

Eine viel schnellere Möglichkeit, eine Datenbankdatei zu verkleinern, ist folgende:

  • Ordnen Sie der Datenbank eine neue Dateigruppe zu
  • Machen Sie diese Dateigruppe so groß wie sie sein muss (verwenden Sie sp_spaceused um festzustellen, wie groß)
  • Erstellen Sie alle Indizes für diese neue Dateigruppe neu
  • Löschen Sie die alte Dateigruppe

Da Indexwiederherstellungen massiv parallel sind, führt diese Technik häufig zu einem viel schnelleren Verkleinern der Datenbank. Natürlich müssen Sie während des Vorgangs etwas zusätzlichen Speicherplatz für die neue Dateigruppe haben. Sie benötigen jedoch nur genügend Speicherplatz in der neuen Dateigruppe, um die größte Dateigruppe in der Instanz aufzunehmen (da Sie im Laufe der Zeit Speicherplatz zurückfordern werden).

Diese Technik hat auch den zusätzlichen Vorteil, dass Ihre Indizes dabei defragmentiert werden.

15
Thomas Kejser

Ich habe die Abfrage ein wenig optimiert, um nur das angeforderte LOG zu verkleinern:

set nocount on  
SELECT 
      'USE [' + d.name + N']' + CHAR(13) + CHAR(10) 
    + 'DBCC SHRINKFILE (N''' + mf.name + N''' , 0, TRUNCATEONLY)' 
    + CHAR(13) + CHAR(10) + CHAR(13) + CHAR(10) 
FROM 
         sys.master_files mf 
    JOIN sys.databases d 
        ON mf.database_id = d.database_id 
WHERE d.database_id > 4 and mf.type_desc = 'LOG'
13
Frankachela

Mit dem folgenden Code erhalten Sie eine Liste der Nicht-Systemdatenbanken. Stellen Sie die Datenbank auf schreibgeschützt ein und verkleinern Sie die Datei. Ich habe diesen Code in einigen SQL Server-Feldern mit SQL Agent Job gespeichert, wobei Speicherplatz immer ein Problem darstellt. Jede Woche in der Sa/So-Nacht wird es ausgeführt und alle Datenbanken werden innerhalb weniger Stunden verkleinert (abhängig von der Größe der Datenbanken).

declare @db varchar(255)
declare c cursor for
select name from sys.databases where is_read_only=0 and state=0
  and name not in ('master','model','tempdb','msdb')
open c
fetch c into @db
while @@fetch_status=0
begin
  exec SP_dboption @db,'trunc. log on chkpt.','true' 
  DBCC shrinkdatabase (@db)
  fetch next from c into @db
end
close c
deallocate c

Dieser erweitert die obige Antwort und verwendet einen Cursor, um die SQL-Anweisungen einzeln zu durchlaufen. Es ist nicht so kurz wie Emrahs Antwort, aber es erlaubt zusätzliche Logik innerhalb der while-Schleife innerhalb des Cursors.

SELECT 
    'USE [' 
    + databases.name + N']' 
    + CHAR(13) 
    + CHAR(10) 
    + 'DBCC SHRINKFILE (N''' 
    + masterFiles.name 
    + N''' , 0, TRUNCATEONLY)' 
    + CHAR(13) 
    + CHAR(10) 
    + CHAR(13) 
    + CHAR(10)                                                                  AS sqlCommand
INTO
    #shrinkCommands
FROM 
    [sys].[master_files] masterFiles 
    INNER JOIN [sys].[databases] databases ON masterFiles.database_id = databases.database_id 
WHERE 
    databases.database_id > 4; -- Exclude system DBs


DECLARE iterationCursor CURSOR

FOR
    SELECT 
        sqlCommand 
    FROM 
        #shrinkCommands

OPEN iterationCursor

DECLARE @sqlStatement varchar(max)

FETCH NEXT FROM iterationCursor INTO @sqlStatement

WHILE (@@FETCH_STATUS = 0)
BEGIN
    EXEC(@sqlStatement)
    FETCH NEXT FROM iterationCursor INTO @sqlStatement
END

-- Clean up
CLOSE iterationCursor
DEALLOCATE iterationCursor
DROP TABLE #shrinkCommands
0
Alistair

Verkleinern Sie alle Protokolldateien außer Master, Model, MSDB:

EXEC sp_MSforeachdb '
DECLARE @sqlcommand nvarchar (500)
IF ''?'' NOT IN (''master'', ''model'', ''msdb'')
BEGIN
USE [?]
SELECT @sqlcommand = ''DBCC SHRINKFILE (N'''''' + 
name
FROM [sys].[database_files]
WHERE type_desc = ''LOG''
SELECT @sqlcommand = @sqlcommand + '''''' , 0)''
EXEC sp_executesql @sqlcommand
END'
0
Emrah Saglam

Wir können SHRINKDB und SHRINKFILE für alle Datenbanken dynamisch wiederholen:

while @DBID<[email protected]
begin
  -- Used Dynamic SQL for all databases.
  Set @SQL ='Use '[email protected]+ ' '+Char(10)
  Set @SQL += 'DBCC SHRINKFILE('[email protected]+',5)' +Char(10)
  Set @SQL += 'DBCC SHRINKDATABASE('[email protected]+')'+Char(10)

  --#6 Increment DBid for looping over all databases
  Set @DBID = @DBID+1
  Select @DBName = DBName, @Filename=DBFileName from #DBNames where [dbid] = @DBID and type_Desc = 'LOG'
  Print (@SQL)
  Exec (@SQL)
end

Details finden Sie in dieser Artikel .

0
Anup Kulkarni