Libération de la table SQL Server de l'espace inutilisé


11

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 | INUTILISÉ |
| ------------- | -------- | -------------- | ----------- --- | ------------ | -------------- |
| MyTableName | 158890 | 8928296 KB | 5760944 KB | 2248 KB | 3165104 KB |

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 remplacée ScanImagesur chaque ligne par une image beaucoup plus petite (c'est ainsi qu'il y a tellement d'espace inutilisé).

Réponses:


10

La seule chose que nous avons faite est remplacée ScanImageà 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'avais l'habitude SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;d'empêcher toute modification simultanée de se produire pendant ou après la copie et d'être perdue.

Le nombre de pages LOB réservées après réduction de la taille d'un imagedans 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 |
+ ------------------------------------------------- - + --------------------- + ------------------------- +

1
Ou si la table est grande, les données BCP sortent, puis BULK INSERT réintègre - pendant la fenêtre de maintenance.
Kin Shah

6

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 de place supplémentaire car 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 deALTER 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")

La documentation en ligne (BOL) contient un excellent article sur la reconstruction des index sur http://technet.microsoft.com/en-us/library/ms188388%28v=sql.100%29.aspx


2

Assurez-vous que le mode de récupération de base de données est SIMPLE.

modifier la colonne comme VARBINARY(MAX).

Essayez ensuite de copier les données dans une toute nouvelle table.

Vérifiez la nouvelle taille de table à 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 mentionnées 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.


1

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.)

  1. Ajoutez un nouveau fichier au groupe de fichiers.
  2. Courez DBCC SHRINKFILE(file, EMPTYFILE). Puisque vous réduisez le MDF, il finira par échouer, car les métadonnées système ne peuvent pas être déplacées. Toutefois, les allocations d'objets blob vides ne sont pas déplacées.
  3. Courez DBCC SHRINKFILE(newfile,EMPTYFILE). Cela fera reculer les données, moins l'espace excédentaire.
  4. Déposez le nouveau fichier (maintenant vide) du groupe de fichiers.

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.


-1

Réorganisez l'index clusterisé - que l'on a les données aux nœuds, donc ... il est probablement fragmenté.


J'ai essayé de lancer: ALTER INDEX ALL ON [MyTableName] REORGANIZE;
DermFrench

3
Reconstruisez-le;) Ne réorganisez pas.
TomTom
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.