Dans SQL Server (2008 dans ce cas), comment puis-je réduire rapidement tous les fichiers, à la fois le journal et les données, pour toutes les bases de données d'une instance? Je pourrais passer par SSMS et cliquer droit chacun et choisir Tâches -> Rétrécir, mais je cherche quelque chose de plus rapide.
J'ai écrit quelques scripts "Créer une base de données" et j'ai oublié qu'ils avaient des tailles gonflées pour les valeurs par défaut, et n'ont pas besoin de beaucoup d'espace réservé pour ces fichiers sur ce projet.
Lorsque vous effectuez "Tâches -> Rétrécir" à partir de l'interface graphique, il émet en fait un DBCC SHRINKDATABASE
commande dans les coulisses. Essayez-le. Lorsque la boîte de dialogue s'affiche, ne cliquez pas sur le bouton "OK". Cliquez plutôt sur le bouton "Script". Vous verrez la commande dans une fenêtre de requête. Combinez cela avec une requête sur sys.databases (laissez de côté master et msdb), et vous pouvez créer un script pour réduire toutes les bases de données.
Par exemple (extrait du commentaire de 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;
Copiez la sortie de cette requête et exécutez-la pour réduire tous vos fichiers.
Que diriez-vous d'une seule ligne de déclaration SQL?
Veuillez lire ce article de blog très intéressant avant d'exécuter l'instruction sql suivante.
EXEC sp_MSForEachDB 'DBCC SHRINKDATABASE (''?'' , 0)'
DBCC SHRINKDB (et son cousin SHRINKFILE) sont extrêmement lents, car il y a beaucoup d'exécution à thread unique dans ce code.
Un moyen beaucoup plus rapide de réduire un fichier de base de données est le suivant:
sp_spaceused
pour déterminer la taille)Étant donné que les reconstructions d'index sont massivement parallèles, cette technique entraîne souvent une réduction beaucoup plus rapide de la base de données. Bien sûr, cela nécessite que vous ayez un peu d'espace supplémentaire pour le nouveau groupe de fichiers pendant le processus. Cependant, vous n'avez besoin que de suffisamment d'espace dans le nouveau groupe de fichiers pour contenir le plus grand groupe de fichiers de l'instance (car vous récupérerez de l'espace au fur et à mesure).
Cette technique a également l'avantage supplémentaire de défragmenter vos index dans le processus.
J'ai ajusté un peu la requête pour ne réduire que le journal tel qu'il est demandé:
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'
Le code ci-dessous, obtenez une liste des bases de données non système, définissez la base de données en lecture seule, puis réduisez le fichier. J'ai conservé ce code dans quelques boîtes SQL Server à l'aide du travail de l'Agent SQL, où l'espace est toujours un problème. Le samedi/dimanche soir chaque semaine, il commence à fonctionner et réduit toutes les bases de données en quelques heures (selon la taille des bases de données).
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
Celui-ci étend la réponse ci-dessus, en utilisant un curseur pour parcourir les instructions SQL une par une. Ce n'est pas aussi court que la réponse d'Emrah, mais cela permet une logique supplémentaire dans la boucle while du curseur.
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
Rétrécir tous les fichiers journaux sauf 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'
Nous pouvons répéter dynamiquement SHRINKDB
et SHRINKFILE
pour toutes les bases de données:
while @DBID<=@MaxDBID
begin
-- Used Dynamic SQL for all databases.
Set @SQL ='Use '+@DBName+ ' '+Char(10)
Set @SQL += 'DBCC SHRINKFILE('+@Filename+',5)' +Char(10)
Set @SQL += 'DBCC SHRINKDATABASE('+@DBName+')'+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
Vous pouvez trouver des détails dans cet article .