Nous avons récemment effacé les anciennes données de notre base de données de production. La base de données est 3 TB avec 1.4 TB vide ceci, cependant, pose un problème sur l'instance de développement et d'assurance qualité, car nous n'utilisons pas d'espace en disposant de 6 à 8 bases de données avec 1.4 TB espace vide, en particulier avec les contraintes d'espace, nous avons sur le développement. Je souhaite configurer un travail pour réduire les bases de données de développement à l'aide du code ci-dessous.
EXEC sp_MSForEachDB ' USE [?]; DBCC SHRINKFILE (''?'' , 10)'
EXEC sp_MSForEachDB ' USE [?]; DBCC SHRINKFILE (''?'' , 0, TRUNCATEONLY)'
Je reçois l'erreur suivante "Impossible de localiser le fichier" Test "pour la base de données" Test "dans sys.database_files. Le fichier n'existe pas ou n'a pas été supprimé." La base de données contient plusieurs fichiers de données. Comment pourrais-je améliorer mon code pour accueillir les fichiers de données multiples.
@Sp_blitzerik a correctement identifié le problème, mais je proposerais une solution différente: utilisez un script ponctuel qui crée vos déclarations SHRINKFILE
, vérifiez-les pour la santé mentale, puis exécutez-les manuellement. Ou mettez-les dans votre poste d'agent:
SELECT dbname = DB_NAME(),
file_name = name,
TotalMB = CONVERT(decimal(12,1),size/128.0),
UsedMB = CONVERT(decimal(12,1),FILEPROPERTY(name,'SpaceUsed')/128.0),
FreeMB = CONVERT(decimal(12,1),(size - FILEPROPERTY(name,'SpaceUsed'))/128.0),
Command = CONCAT('USE ', DB_NAME(), '; DBCC SHRINKFILE (name = ',
[name], ', size = ',
convert(int,round(1.15 * FILEPROPERTY(name,'SpaceUsed')/128,-1)), 'MB)')
FROM sys.database_files WITH (NOLOCK)
WHERE type_desc = 'ROWS'
ORDER BY file_id;
Exécutez ceci une fois de chaque base de données, il doit renvoyer la taille totale et utilisée pour chaque fichier de données (il saute les fichiers journaux, vous pouvez les réduire instantanément à la main) et un exemple SHRINKFILE
Déclaration qui vous donne une cible de 15% d'espace libre dans le fichier, calculée à partir de l'espace actuel utilisé:
USE myDB; DBCC SHRINKFILE (name = myDBData, size = 148910MB)
Vous devrez vérifier les résultats pour la santé mentale, si le fichier déjà a moins de 15% d'espace libre, alors l'instruction SHRINKFILE
_ Spécifiera une plus grande taille qu'elle n'a actuellement pas Il (c'est déjà assez petit).
Une fois que vous avez rétréci tous les fichiers de données, choisissez une taille de la cible pour chaque fichier log (J'utilise généralement 10-25% de la taille du fichier de données) et rétrécissez ceux à la main. Cela peut dépendre du modèle de récupération, ainsi que de la quantité d'activité de ces DBS dans cet environnement.
La marque d'interrogation évaluera au nom de la base de données et non au nom de fichier que vous essayez de réduire.
Par exemple:
EXEC master.sys.sp_MSforeachdb ' USE [?]; PRINT N''?''; ';
Retournera (sur mon serveur)
master
tempdb
model
msdb
SUPERUSER
StackOverflow
StackOverflow_CS
Crap
DBAtools
StackOverflow2010
SUPERUSER_CX
ಠ_ಠ
StackOverflow2010ಠ_ಠ
DBCC strinkfile ne prend pas cela comme un argument:
DBCC Shrinkfile (
[.____] {Nom de fichier | file_id}
{ [ , FICHIER VIDE ]
[.____] | [[ cible_size] [ {NOTRONCATE | Troncatetonly}]]
[.____]}) [avec no_infomsgs]
Si vous n'avez qu'un fichier .MDF et un .ldf, vous pouvez (probablement, bien que pas certainement) remplacer votre code avec:
EXEC sp_MSForEachDB ' USE [?]; DBCC SHRINKFILE (1 , 10)'
EXEC sp_MSForEachDB ' USE [?]; DBCC SHRINKFILE (2 , 0, TRUNCATEONLY)'
Plus de code verbeux pour rechercher des identifiants de fichier, etc. est laissé comme un exercice au lecteur.
Si vous voulez simplement rétrécir le tout, utilisez-le DBCC Shrinkdatabase à la place. Cela prend un nom de base de données et fonctionnera avec votre code d'origine.
DBCC StrinkDatabase (Nom de base de données | Database_ID | 0
[.____] [ cible_percent]
[.____] [ {NOTRONCATE | Troncatetonly}]) [avec no_infomsgs]
Bien sûr, cela peut causer toutes sortes de problèmes , et je ne voudrais pas le faire.
@Bradc Voici comment j'ai adapté votre code suggéré
CREATE TABLE #ShrinkFile
(
DBName sysname,
File_Name sysname,
TotalMB decimal (18,2),
UsedMB decimal (18,2),
FreeMB decimal (18,2),
Command nvarchar(MAX)
)
EXEC master.sys.sp_MSforeachdb ' USE [?];
Insert Into #ShrinkFile (DBName, File_Name, TotalMB, UsedMB, FreeMB,
Command)
SELECT dbname = DB_NAME(),
file_name = name,
TotalMB = CONVERT(decimal(12,1),size/128.0),
UsedMB = CONVERT(decimal(12,1),FILEPROPERTY(name,''SpaceUsed'')/128.0),
FreeMB = CONVERT(decimal(12,1),(size -
FILEPROPERTY(name,''SpaceUsed''))/128.0),
Command = CONCAT(''USE '', DB_NAME(), ''; DBCC SHRINKFILE (name = '',
[name], '', size = '',
convert(int,round(1.15 *
FILEPROPERTY(name,''SpaceUsed'')/128,-1)), ''MB)'')
FROM sys.database_files WITH (NOLOCK)
WHERE type_desc = ''ROWS''
ORDER BY file_id;'
IF EXISTS (SELECT * FROM #ShrinkFile WHERE FreeMB > 1000)
BEGIN
DECLARE @SQLText nvarchar(max)
DECLARE Shrink_cursor CURSOR FOR
SELECT DISTINCT Command FROM #ShrinkFile
WHERE FreeMB > 1000
OPEN Shrink_cursor
FETCH NEXT FROM Shrink_cursor INTO @SQLText
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC (@SQLText)
FETCH NEXT FROM Shrink_cursor INTO @SQLText
END
CLOSE Shrink_cursor
DEALLOCATE Shrink_cursor
END
DROP TABLE #ShrinkFile