Comment réduire la taille d'une table SQL Server issue d'un changement de type de données
-
03-07-2019 - |
Question
J'ai une table sur SQL Server 2005 d'une taille d'environ 4 Go.
(environ 17 millions d'enregistrements)
J'ai remplacé l'un des champs du type de données char (30)
par char (60)
(il y a au total 25 champs dont la plupart sont char ( 10)
, la quantité d’espace de caractères s’élève donc à environ 300)
La taille de la table a doublé (plus de 9 Go)
J’ai ensuite changé le char (60)
en varchar (60)
, puis j’ai exécuté une fonction permettant de réduire l’espace supplémentaire dans les données (afin de réduire la moyenne longueur des données dans le champ à environ 15)
Cela n'a pas réduit la taille de la table. Réduire la base de données n’a pas aidé non plus.
À moins de recréer la structure de la table et de copier les données (ce qui représente 17 millions d’enregistrements!), existe-t-il un moyen moins radical de réduire la taille?
La solution
Eh bien, il est clair que vous ne récupérez pas d’espace! : -)
Lorsque vous modifiez vos champs de texte en CHAR (60), ils sont tous remplis à pleine capacité avec des espaces. Donc, TOUS vos champs contiennent maintenant réellement 60 caractères.
Le fait de revenir à VARCHAR (60) ne changera rien - les champs ont toujours une longueur de 60 caractères ....
Ce que vous devez vraiment faire, c'est exécuter une fonction TRIM sur tous vos champs pour les ramener à leur longueur ajustée, puis réduire la taille de la base de données.
Après cela, vous devez RECONSTRUIRE votre index clusterisé afin de récupérer une partie de cet espace perdu. L’index clusterisé est vraiment l’endroit où résident vos données - vous pouvez le reconstruire comme suit:
ALTER INDEX IndexName ON YourTable REBUILD
Par défaut, votre clé primaire est votre index clusterisé (sauf indication contraire de votre part).
Marc
Autres conseils
Vous n'avez nettoyé ni compacté aucune donnée, même avec une "base de données réduite".
Récupère de l'espace à partir de colonnes de longueur variable supprimées dans des tables ou des vues indexées.
Cependant, une reconstruction d'index simple < em> s'il existe un index clusterisé devrait également le faire
ALTER INDEX ALL ON dbo.Mytable REBUILD
Je sais que je ne réponds pas à la question que vous posez, mais avez-vous envisagé d'archiver certaines données dans une table d'historique et utilisez-vous moins de lignes?
La plupart du temps, vous pensez peut-être à première vue que vous avez besoin de toutes ces données tout le temps, mais lorsque vous vous asseyez vraiment pour les examiner, il existe des cas où ce n'est pas vrai. Ou du moins j'ai déjà vécu cette situation.
J'ai eu un problème similaire ici SQL Server, conversion de NTEXT en NVARCHAR (MAX) <> / a> qui était lié à la modification de ntext en nvarchar (max).
Je devais faire un UPDATE MyTable SET MyValue = MyValue
afin de pouvoir tout redimensionner correctement.
Cela prend évidemment beaucoup de temps avec beaucoup d’enregistrements. Il y avait un certain nombre de suggestions sur la meilleure façon de le faire. La clé 1 était un drapeau temporaire indiquant si cela avait été fait ou non, puis en mettant à jour plusieurs milliers à la fois en boucle jusqu'à ce que tout soit terminé. Cela signifiait que j'avais "quelques" contrôle sur combien il faisait.
Sur une autre note cependant, si vous voulez vraiment réduire la base de données autant que possible, il peut être utile de réduire le modèle de récupération en simple, de réduire les journaux de transactions, de réorganiser toutes les données des pages, puis de les définir. retour au modèle de récupération complète. Cependant, soyez prudent, il est généralement déconseillé de réduire les bases de données. Si vous réduisez le modèle de récupération d'une base de données active, vous demandez que quelque chose ne se passe pas bien.
Vous pouvez également procéder à une reconstruction complète de la table pour vous assurer qu'aucune donnée supplémentaire ne traîne nulle part:
CREATE TABLE tmp_table(<column definitions>);
GO
INSERT INTO tmp_table(<columns>) SELECT <columns> FROM <table>;
GO
DROP TABLE <table>;
GO
EXEC sp_rename N'tmp_table', N'<table>';
GO
Bien sûr, les choses se compliquent d'identité, d'index, etc. etc.