it-swarm.it

Come posso ridurre rapidamente tutti i file per tutti i database?

In SQL Server (2008 in questo caso) come posso ridurre rapidamente tutti i file, sia di registro che di dati, per tutti i database su un'istanza? Potrei passare attraverso SSMS e fare clic con il tasto destro su ciascuno e scegliere Attività -> Riduci, ma sto cercando qualcosa di più veloce.

Ho scritto alcuni script "Crea database" e ho dimenticato che avevano dimensioni in mongolfiera per impostazione predefinita, e non ho bisogno di molto spazio riservato per questi file in questo progetto.

47
jcolebrand

Quando esegui "Attività -> Riduci" dalla GUI, viene effettivamente emesso un DBCC SHRINKDATABASE comando dietro le quinte. Provalo. Quando viene visualizzata la finestra di dialogo, non fare clic sul pulsante "OK". Invece, fai clic sul pulsante "Script". Vedrai il comando in una finestra di query. Combinalo con una query su sys.database (tralascia master e msdb) e puoi creare uno script per ridurre tutti i database.

Ad esempio (tratto dal commento di 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;

Copia l'output di quella query ed eseguilo per ridurre tutti i tuoi file.

59
Larry Coleman

Che ne dici di una singola riga di istruzione sql?

Si prega di leggere this post di blog molto interessanti prima di eseguire la seguente istruzione sql.

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

DBCC SHRINKDB (e suo cugino SHRINKFILE) sono estremamente lenti, perché in quel codice è in corso molta esecuzione a thread singolo.

Un modo molto più veloce per ridurre un file di database è questo:

  • Allocare un nuovo filegroup al database
  • Rendi questo filegroup grande come deve essere (usa sp_spaceused per determinare quanto è grande)
  • Ricostruisci tutti gli indici in questo nuovo filegroup
  • Rilascia il vecchio filegroup

Poiché le ricostruzioni degli indici sono enormemente parallele, questa tecnica si traduce spesso in una riduzione molto più rapida del database. Ovviamente, ti richiede di avere un po 'di spazio extra per il nuovo filegroup mentre il processo è in corso. Tuttavia, nel nuovo filegroup è necessario solo spazio sufficiente per contenere il filegroup più grande nell'istanza (poiché verrà recuperato lo spazio man mano che si procede).

Questa tecnica ha anche l'ulteriore vantaggio di deframmentare gli indici nel processo.

15
Thomas Kejser

Ho ottimizzato un po 'la query per ridurre solo il LOG come richiesto:

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

Il codice seguente, ottiene un elenco di database non di sistema, imposta il database in sola lettura e quindi riduce il file. Ho conservato questo codice in alcune caselle di SQL Server utilizzando SQL Agent Job, dove lo spazio è sempre un problema. Ogni sabato/domenica notte inizia a funzionare e riduce tutti i database in poche ore (a seconda della dimensione dei database).

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

Questo estende la risposta sopra, usando un cursore per scorrere una alla volta le istruzioni SQL. Non è breve come la risposta di Emrah, ma consente una logica aggiuntiva all'interno del ciclo while all'interno del cursore.

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

Riduci tutti i file di registro tranne master, modello, 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

Possiamo ripetere SHRINKDB e SHRINKFILE per tutti i database in modo dinamico:

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

Puoi trovare i dettagli in questo articolo .

0
Anup Kulkarni