J'ai une table dans SQL Server 2012 Express avec beaucoup d'espace inutilisé.
J'ai besoin de libérer de l'espace dans la base de données.
| NOM | ROWS | RÉSERVÉ | DONNÉES | INDEX_SIZE | NON UTILISÉ | | ------------- | -------- | -------------- | ---- ---------- | ------------ | -------------- | | MyTableName | 158890 | 8928296 KB | 5760944 KB | 2248 KB | 3165104 Ko |
Comment puis-je obtenir SQL pour libérer le 3165104KB?
J'ai déjà essayé:
Alter table MyTableName Rebuild
DBCC CLEANTABLE (MyDbName,"MyTableName ", 0)
ALTER INDEX ALL ON MyTableName REORGANIZE ;
ALTER INDEX PK_Image ON MyTableName REBUILD WITH (ONLINE = OFF)
Voici le tableau:
CREATE TABLE [dbo].[MyTableName](
[ImageID] [int] IDENTITY(1,1) NOT NULL,
[DateScan] [datetime] NULL,
[ScanImage] [image] NULL,
CONSTRAINT [PK_Image] PRIMARY KEY CLUSTERED
(
[ImageID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 100) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
La seule chose que nous avons faite est de remplacer ScanImage
sur chaque ligne par une image beaucoup plus petite (c'est ainsi qu'il y a tellement d'espace inutilisé).
La seule chose que nous avons faite est de remplacer
ScanImage
sur chaque ligne par une image beaucoup plus petite (c'est ainsi qu'il y a tellement d'espace inutilisé)
Après avoir fait quelques expériences, la méthode la plus efficace en termes d'espace serait de supprimer l'unité d'allocation et de la repeupler (si vous avez une fenêtre de maintenance pour le faire).
Exemple de code qui a obtenu la meilleure réduction d'espace pour moi avec la structure de table dans la question est:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET XACT_ABORT ON;
BEGIN TRAN
SELECT [ImageID],
[ScanImage]
INTO #Temp
FROM [dbo].[MyTableName]
ALTER TABLE [dbo].[MyTableName]
DROP COLUMN [ScanImage]
/*Allocation unit not removed until after this*/
ALTER INDEX PK_Image ON MyTableName REBUILD
ALTER TABLE [dbo].[MyTableName]
ADD [ScanImage] IMAGE NULL
UPDATE [dbo].[MyTableName]
SET [ScanImage] = T.[ScanImage]
FROM [dbo].[MyTableName] M
JOIN #Temp T
ON M.ImageID = T.[ImageID]
DROP TABLE #Temp
COMMIT
Tout est dans une transaction, donc si la machine tombe en panne, elle sera annulée. Pourrait probablement faire avec une gestion des erreurs ou au moins SET XACT_ABORT ON
. J'ai utilisé SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
pour éviter que des modifications simultanées ne surviennent pendant ou après la copie et soient perdues.
Le nombre de pages LOB réservées après réduction de la taille d'un image
dans toutes les lignes était le suivant:
+ -------------------------------------------- ------ + --------------------- + --------------------- ---- + | Événement | lob_used_page_count | lob_reserved_page_count | + ------------------------------------------ -------- + --------------------- + ------------------- ------ + | 10 000 lignes insérées avec 100 000 octets de données chacune | 135005 | 135017 | | Mise à jour de toutes les lignes en données d'image de 10 000 octets | 31251 | 135012 | | Réorganiser | 23687 | 25629 | | Déposer et rajouter des données d'image | 13485 | 13489 | + ------------------------------------------ -------- + --------------------- + ------------------- ------ +
Essayer
ALTER INDEX PK_Image ON MyTableName REBUILD WITH (ONLINE = OFF)
Cela recrée l'index clusterisé, vous aurez donc besoin de plus d'espace dans votre base de données pour que l'opération se termine. Si vous n'avez pas d'espace supplémentaire parce que votre disque est plein, vous pouvez éventuellement ajouter un nouveau fichier de données à la base de données (sur un autre disque) et y déplacer la table.
Il est également possible que l'index clusterisé soit défini avec un FILLFACTOR inférieur à 100%. Si le facteur de remplissage était défini sur, par exemple 66%, il resterait 1/3 de chaque page de données vide pour une utilisation future. Si tel est le problème, vous pouvez modifier le facteur de remplissage à l'aide de ALTER INDEX PK_Image ON MyTableName REBUILD WITH (ONLINE = OFF, FILLFACTOR=100)
Si vous avez récemment supprimé un champ de longueur variable de la table, vous pouvez également essayer DBCC CLEANTABLE( Databasename, "MyTableName")
Books online (BOL) contient un excellent article sur la reconstruction des index sur http://technet.Microsoft.com/en-us/library/ms188388%28v=sql.100%29.aspx
Assurez-vous que le mode de récupération de base de données est SIMPLE
.
modifiez la colonne comme VARBINARY(MAX)
.
Essayez ensuite de copier les données dans une toute nouvelle table.
Vérifiez la nouvelle taille du tableau à l'aide de sp_spaceused "tablename"
. Si vous êtes satisfait de l'espace inutilisé de la table, vérifiez l'espace inutilisé de la base de données à l'aide de la même commande sans spécifier de nom de table. Cet espace se trouve toujours dans les fichiers de base de données et n'est pas libéré sur le système d'exploitation.
Vous pouvez supprimer la table d'origine et renommer la nouvelle table, ou refaire la même chose et utiliser le nom de la table d'origine si vous ne faites pas confiance à l'opération de renommage (je ne fais pas entièrement confiance).
Si cela fonctionne, la dernière étape est simple: vous savez comment réduire les fichiers et libérer de l'espace inutilisé.
S'il existe des clés étrangères, enregistrez leurs définitions, supprimez-les, effectuez les tâches que je mentionne ci-dessus et recréez les clés étrangères par la suite. Bien sûr, cela prendra du temps et cette opération doit être effectuée pendant les périodes de repos. Toute cette tâche peut également être effectuée via un script pour le laisser s'exécuter pendant la nuit.
Je voudrais simplement créer une nouvelle base de données et y copier les données. Vous devriez pouvoir utiliser l'assistant d'importation/exportation. (Évidemment, une sauvegarde et une restauration garderaient le problème.) Consultez les résultats de l'importation des données. Si tout semble correct, renommez la base de données d'origine, puis renommez la nouvelle base de données avec le nom que vous souhaitez utiliser. (J'attends toujours un peu avant de déposer l'original, juste pour avoir une double vérification en ligne.)
Pour ce que cela vaut, nous avons également récupéré l'espace blob des bases de données, si elles ne sont pas trop grandes, par les étapes suivantes. (Cependant, étant donné que vous utilisez SQL Server Express, vous n'aurez peut-être pas la possibilité d'essayer.)
DBCC SHRINKFILE(file, EMPTYFILE)
. Étant donné que vous réduisez le MDF il échouera finalement, car les métadonnées système ne peuvent pas être déplacées. Cependant, les allocations de blob vides ne sont pas déplacées.DBCC SHRINKFILE(newfile,EMPTYFILE)
. Cela fera reculer les données, moins l'espace excédentaire.Cela élimine le ballonnement blob. Je dois mentionner que nous avons utilisé cette technique principalement pour créer une base de données essentiellement vide pour tester les scripts de mise à niveau.