web-dev-qa-db-fra.com

La base de données SQL Server ne rétrécit pas

J'ai une base de données SQL avec beaucoup d'espace inutilisé. Cependant, lorsque j'exécute des tâches | Rétrécir | Base de données et tâches | Rétrécir | Les fichiers du studio de gestion ne libèrent aucun espace.
Malheureusement, la machine sur laquelle il s'exécute manque d'espace sur le disque dur. Toutes les idées sur la raison pour laquelle cet espace ne se libère pas.

Le mode de récupération sur DB est également défini sur simple. enter image description here

Voici la boîte de dialogue inutilisée qui s'affiche lorsque je vais réduire les fichiers: enter image description here

J'ai également essayé de le faire via T-SQL

DBCC SHRINKDATABASE (myDatabase, 5);

J'obtiens la réponse suivante:

DBCC SHRINKDATABASE: l'ID de fichier 1 de l'ID de base de données 6 a été ignoré car le fichier n'a pas suffisamment d'espace libre pour récupérer. DBCC SHRINKDATABASE: l'ID de fichier 2 de l'ID de base de données 6 a été ignoré car le fichier n'a pas suffisamment d'espace libre pour récupérer. L'exécution de DBCC est terminée. Si DBCC a imprimé des messages d'erreur, contactez votre administrateur système.

18
DermFrench

Je vais faire une supposition sauvage et dire que votre base de données est configurée pour utiliser la récupération complète. Vous n'avez jamais pris de sauvegarde (et encore moins une copie complète) sur la base de l'image ci-dessus. Si tel est le cas, votre fichier journal grandit de plus en plus et ne peut pas disparaître car vous n'avez pas effectué de sauvegarde.

Si vous avez la salle de faire une sauvegarde complète, puis une sauvegarde du journal et essayez à nouveau votre rétrécissement. Devrait bien fonctionner.

Le pire des cas (et je veux dire le pire, en particulier s'il s'agit d'une base de données de production) consiste à définir la base de données sur une récupération SIMPLE, à la réduire puis à effectuer une sauvegarde. Cela devrait fonctionner même si vous n'avez pas assez d'espace pour un rétrécissement normalement.

À ce stade, assurez-vous de configurer des sauvegardes régulières pour votre base de données.

Vous pouvez aller ici pour plus de détails.


MODIFIER:

Pouvez-vous nous dire quel% du journal est gratuit par rapport au fichier de données? Vous pouvez également consulter le log_reuse_wait_desc dans sys.databases.

SELECT name, log_reuse_wait_desc FROM sys.databases 

Et enfin et surtout, avez-vous essayé l'option TRUNCATEONLY de rétrécir?

DBCC SHRINKFILE (Adventureworks2008R2_Log, TRUNCATEONLY)
6
Kenneth Fisher

Vous devez également réduire les fichiers pour récupérer l'espace disque: Tâches | Rétrécir | Fichiers dans SQL Server Management Studio

Vous devez cocher l'option "Réorganiser les fichiers avant de libérer de l'espace inutilisé" et définir un pourcentage d'espace libre, en fonction de la croissance attendue de votre base de données.

5
Rom Eh

Eh bien, cela pourrait avoir plusieurs raisons. Je mentionnerai toutes les raisons possibles et définirai ensuite des solutions pour résoudre le problème.

  1. Comme le mentionne votre sortie DBCC, vous n'avez pas assez d'espace disque disponible pour réduire le fichier de base de données. En d'autres termes. Vous essayez de déplacer des pages de votre fichier de base de données vers un fichier nouvellement créé. Pendant ce temps, les pages existent deux fois. Ensuite, SQL Server supprimera l'ancien fichier de base de données et prendra le fichier nouvellement créé pour une utilisation en production. Vous devrez peut-être augmenter votre espace disque ou suivre la solution mentionnée ci-dessous.
  2. Un autre point qui empêchera la réduction, peut être un verrou de base de données (ce qui n'est pas votre cas). Si la base de données est verrouillée pendant les modifications DDL, elle ne pourra pas réduire le fichier de base de données. Si vous réduisez le fichier avec l'assistant, vous rencontrez probablement un message d'expiration de temps en temps. Si vous l'exécutez en tant que script, il attendrait normalement jusqu'à ce que le verrou soit libéré, puis réduirait le fichier.

Solutions possibles

La solution la plus simple est la planification! Vérifiez votre base de données et essayez d'évaluer combien de données seront insérées par jour, déterminez le taux de croissance. Par défaut, SQL Server augmentera un fichier de 10%. Ce n'est pas mauvais pour les bases de données qui ne contiennent que 100 Mo, car la croissance ne serait que de 10 Mo. Mais si votre base de données s'agrandit et augmente, la croissance coûtera beaucoup de ressources et de temps (100 Go -> 10 Go, 1 To -> 100 Go, etc.). Définissez un facteur de croissance en Mo. Il ne doit pas être trop petit (par exemple 1 Mo) car cela mettra votre disque sur une grosse transaction et ralentira vos opérations, mais pas trop pour provoquer une énorme opération d'écriture (par exemple 10 Go).

Définissez en outre une limite de croissance sur les bases de données qui peut augmenter (par exemple, journalisation des bases de données). La transaction peut échouer si la limite est atteinte, mais cela ne fera pas trop de mal aux bases de données de journalisation. Mais si votre base de données de journalisation utilise tout votre espace disque disponible, cela peut entraîner un abandon/annulation de transaction sur une base de données de production.

Si vous avez le problème, que votre espace disque est trop petit et ne pourra plus contenir l'espace disque utilisé (par exemple: fichier de 140 Go, 40 Go gratuit, signifie 100 Go à réorganiser -> vous avez besoin d'au moins 100 Go d'espace libre supplémentaire pour le temps de la rétraction sur une opération en mouvement), vous pouvez toujours récupérer un peu d'espace en utilisant l'indicateur TRUNCATEONLY.

DBCC SHRINKFILE (1,TRUNCATEONLY)

Cela supprimera toutes les pages de données vides qui sont retenues à la fin de votre fichier de base de données avec le file_id = 1. Retour à notre exemple de 140 Go: Si votre fichier de base de données de 140 Go contient la dernière page écrite à la position de 120 Go, vous obtiendrez le dernier 20 Go presque instantanément de retour. Ce processus est assez rapide, car il déplace simplement le marqueur de fin de fichier à la position de 120 Go et informera votre système d'exploitation de l'espace libre.

Vous pouvez obtenir un aperçu rapide de vos fichiers de base de données à l'aide de cette requête:

SELECT *
FROM sys.sysfiles

Si vous avez suffisamment d'espace libre sur le disque (ou après avoir exécuté le TRUNCATEONLY sur chaque fichier), vous devriez être en mesure de vraiment nettoyer vos fichiers de base de données et vraiment les réduire.

Cela pourrait être réalisé en utilisant la déclaration suivante:

DBCC SHRINKFILE (1);

Si vous avez une table de base de données qui est souvent écrite ou exécute des transactions souvent plus importantes, je suggère de définir une limite cible. Cela dépend de votre expérience avec cette base de données. Normalement de 5 à 10% (selon la taille de la base de données), mais un minimum de 100 à 1 000 Mo doit être défini. Comme exemple sur notre fichier de base de données de 140 Go (40 Go vide), la taille cible doit être définie sur 110 Go (100 Go utilisés + 10% de réserve).

Vous pouvez y parvenir en utilisant cette déclaration:

DBCC SHRINKFILE (1,112640); -- 110GB in MB

Mais attention, cela peut durer très longtemps (selon la taille de votre fichier et votre sous-système d'E/S). Comme vous créerez une charge de travail plus importante sur votre sous-système d'E/S, je suggère d'exécuter de tels scripts dans des temps de chargement faibles (peut-être du jour au lendemain).

Si vous voulez vraiment nettoyer vos fichiers de base de données, ce serait une bonne idée de vérifier tous vos index et REBUILD ou REORGANIZE tous les index qui ont une forte fragmentation.

Si vous êtes sur une machine de développement ou êtes vraiment prêt à prendre un risque, vous pouvez exécuter cette instruction. Il itérera sur chaque index de votre base de données et le reconstruira.

DECLARE @sql nvarchar(max), @sch nvarchar(max), @obj nvarchar(max), @ind nvarchar(max)

DECLARE cur CURSOR FOR
    SELECT s.name, o.name, i.name
    FROM sys.objects as o
    INNER JOIN sys.schemas as s
            ON o.schema_id = s.schema_id
    INNER JOIN sys.indexes as i
            ON o.object_id = i.object_id
    WHERE i.type > 0 

OPEN cur

FETCH NEXT FROM cur INTO @sch, @obj, @ind

WHILE @@FETCH_STATUS = 0 BEGIN

    SET @sql =  N'ALTER INDEX ['+@ind+'] ON ['+@sch+'].['+@obj+'] ' 
                + N'REBUILD PARTITION = ALL '
                + N'WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, '
                + N'ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)'
    PRINT(@sql) EXEC (@sql)

    FETCH NEXT FROM cur INTO @sch, @obj, @ind
END

CLOSE cur
DEALLOCATE cur

Après ce processus, votre fichier de base de données peut être agrandi à nouveau. Mais vous pourrez le réduire à une taille de fichier beaucoup plus faible à mesure que l'espace libre de chaque index sera supprimé.

Avertissement et informations supplémentaires

Soyez prudent lorsque vous réduisez vos fichiers de base de données. Il y a une bonne raison pour que SQL Server alloue de l'espace fichier à l'avance. Les allocations de disques coûtent cher, les faire le moins possible est une bonne idée. Si vous avez une base de données très agile qui produit chaque jour une surcharge de quelques Go et la libère après un certain temps, il ne sera pas bon de réduire toujours le fichier au minimum. Vous gaspillez de l'énergie du disque pour agrandir le fichier, faites votre travail et gaspillez à nouveau l'énergie du disque pour réduire à nouveau le fichier. Dans de tels cas, soyez conscient de gaspiller un peu d'espace disque pour améliorer vos opérations de données.

Espérons que ce long résumé vous aidera à résoudre votre problème et vous aidera même à faire un plan pour vos bases de données.

5
Ionic

Vérifiez le paramètre de taille initiale dans Propriétés -> Fichiers. L'initiale doit lire au minimum, vous ne pouvez pas réduire en dessous, quelle que soit la quantité d'espace libre.

4
Ethan Drotning

Avant de réduire, vous devez vérifier la plénitude de la page de l'index cluster de vos plus grandes tables

Page fullness and fragmentation[Plénitude et fragmentation des pages]

Faites le reconstruire Rebuild clustered index[Reconstruire un index clusterisé]

Rétrécir le fichier de données: tâches | Rétrécir | Fichiers dans SQL Server Management Studio avec "Réorganiser les fichiers avant de libérer de l'espace inutilisé"

P.S. Veuillez noter qu'après Shrink, vous obtiendrez une base de données très fragmentée qui peut affecter les performances

3
AlexK