Quel effet la réduction de la taille d'une colonne varchar aura-t-elle sur le fichier de base de données?

15

Nous avons un certain nombre de tables dans notre base de données qui ont des VARCHAR(MAX)colonnes où un VARCHAR(500)(ou quelque chose de beaucoup plus petit que max) suffira. Naturellement, je veux les nettoyer et ramener les tailles à des niveaux plus raisonnables. Le «comment» faire cela, je le comprends: ma question est de savoir ce que la modification de ces colonnes aura sur les pages et les extensions présentes sur le disque. (Il y a beaucoup d'informations sur ce qui se passe lorsque vous développez une colonne, mais vous avez du mal à trouver des informations sur ce qui se passe lorsque vous en réduisez une.)

Certaines tables ont un très petit nombre de lignes, donc je ne m'inquiète pas du coût du changement, mais certaines sont assez grandes et je crains qu'elles ne soient potentiellement réorganisées et provoquent beaucoup de blocages / temps d'arrêt. Concrètement, je veux juste un moyen d'estimer une fenêtre de maintenance. En général, j'aimerais mieux comprendre comment le moteur de base de données se comporte dans ce cas.

Merci d'avance!

ÉDITER:

J'ai 20 tables que je regarde, bien que seulement la moitié d'entre elles aient un nombre de lignes supérieur à 1 000. Le plus grand compte près d'un million de lignes. Le pire délinquant est un tableau avec 350 000 lignes et quatre VARCHAR(MAX)colonnes qui peuvent être réduites au VARCHAR(500)niveau.

nateirvin
la source

Réponses:

12

Tout d'abord: combien de données y a-t-il dans le tableau? Nombre de lignes et taille de la table?

Deuxièmement: pouvez-vous sauvegarder et restaurer cette table sur un serveur de test et exécuter l'instruction alter pour voir l'impact (en supposant qu'elle n'est pas irréalisable car la table est trop grande pour tenir sur un système non-Production)? Je trouve toujours que les tests dans mon environnement sont plus précis que les conseils des interwebs car il y a plusieurs facteurs qui peuvent influencer le résultat qui pourraient ne pas être fournis dans la question simplement parce que je ne sais pas que ces facteurs pourraient affecter le résultat.

Troisièmement: augmenter la taille d'un champ de longueur variable est (en supposant que vous ne dépassez pas la limite de 8060 octets) une simple opération de métadonnées car aucune donnée réelle ne changerait pour une telle opération. MAIS, d'autre part, réduire la taille d'un champ de longueur variable, même à quelque chose qui fonctionnera plus qu'évidemment, n'est pas un simple changement de métadonnées parce que SQL Server ne sait pas, avant d'analyser toutes les lignes , que la nouvelle taille demandée est valide.

Par conséquent: Oui, cela verrouillera la table pendant un certain temps . Combien de temps? Eh bien, voici le test que je viens de faire:

J'avais, à partir d'autres tests, une table avec un seul INT NOT NULLchamp et 1 million de lignes. Je l'ai copié dans une nouvelle table dans le but de faire ce test via:

SELECT *, CONVERT(NVARCHAR(MAX), NEWID()) AS [StringField]
INTO dbo.ResizeTest
FROM dbo.ClusteredUnique;

De cette façon, je commençais avec un scénario similaire d'avoir un MAXchamp (je viens de réaliser que vous avez VARCHARet j'utilise NVARCHAR, mais cela ne devrait pas changer le comportement que je vois) que je pourrais ensuite changer 500. Et il contient des données pouvant facilement contenir jusqu'à 500 caractères. Cela a pris quelques minutes.

J'ai ensuite couru:

ALTER TABLE dbo.ResizeTest ALTER COLUMN [StringField] NVARCHAR(500) NULL;

Et cela a pris un peu plus de 11 minutes.

Je viens de relancer le test, cette fois en laissant tomber le [ResizeTest]tableau et en changeant les deux NVARCHARpour être juste VARCHAR, juste pour être très sûr que je compare les pommes à quelque chose qui ressemble au moins à une pomme ;-).

La création de la table initiale a pris 20 secondes tandis que la création a ALTER TABLEduré 2 minutes.

Donc, en termes d'estimation des temps d'arrêt, cela est vraiment difficile à faire car il est basé sur les vitesses d'E / S du disque, que des opérations de croissance automatique doivent ou non se produire sur le fichier de données et / ou le journal des transactions, etc. C'est probablement une grande partie de la raison pour laquelle mon premier test a pris 11 minutes à modifier et le second, même avec la VARCHARmoitié de la taille des NVARCHARdonnées, n'a pris que 2 minutes (c'est-à-dire que les fichiers ont été pré-développés à ce stade). Mais encore, vous devez garder à l'esprit que mon test s'exécute sur mon ordinateur portable qui n'est pas le disque le plus rapide, mais il ne s'agissait que de 1 million de lignes de 2 petites colonnes (environ 22 octets par ligne).

Et puisque vous avez demandé ce que cela ferait aux pages de données, voici votre réponse. J'ai fait un sp_spaceusedaprès avoir créé la table, après avoir fait le ALTER COLUMN, et après avoir fait ALTER TABLE dbo.ResizeTest REBUILD;. Les résultats (les nombres suivants sont basés sur le deuxième test utilisant VARCHAR, pas sur le premier test utilisant NVARCHAR):

After initial table creation:        526,344 KB
After ALTER COLUMN VARCHAR(500):   1,031,688 KB  <--- !! Yikes!!
After ALTER REBUILD:                 526,472 KB

Si vous êtes préoccupé par la nécessité de maintenir l'opération dans les plus brefs délais, consultez un article que j'ai écrit à ce sujet: Restructurer 100 millions de lignes (ou plus) de tables en secondes. SRSLY! (inscription gratuite requise).

Solomon Rutzky
la source
2
J'ai donc copié la pire table sur mon instance locale (c'est-à-dire un disque plus lent et 1/3 des cœurs). J'ai ALTERédité chaque colonne successivement - chaque action a pris moins d'une seconde. Au moment où ils ont été faits, la table avait doublé de taille, mais une fois que j'ai fait une opération REBUILD(qui était également une seconde), la table est revenue à sa taille d'origine.
nateirvin
@nateirvin C'est bon à entendre. Vous pouvez probablement accélérer l' ALTER TABLEopération en faisant tous les champs en une seule fois, en séparant chaque colonne par une virgule. Si la transaction est trop importante, divisez le tableau en 2 instructions ALTER de la moitié des colonnes chacune. Et selon la taille de la table, vous pouvez même faire une RECONSTRUCTION entre chacune des deux instructions ALTER. Quelque chose avec lequel jouer. Gardez également à l'esprit que l'opération prendra probablement un verrou de schéma pour la durée qui bloquera tout accès à la table.
Solomon Rutzky
1
J'ai fait chacun ALTERséparément pour que je puisse suivre les changements de taille entre chacun, mais certainement bon à savoir. Merci!
nateirvin
1

D'après ce que j'ai rassemblé, l'exécution de l'instruction alter ne devrait pas prendre très longtemps, car la table n'est pas verrouillée par un autre processus. Selon gbn, ce n'est qu'un changement de métadonnées: /programming/7261909/is-it-bad-to-use-alter-table-to-resize-a-varchar-column-to-a-larger -Taille

En outre, quant à la façon dont ils sont stockés, il semble que SQL Server ait stocké les données varchar dans une page de 8 Ko jusqu'à ce qu'il remplisse une page entière, qui à ce stade, il la remplace par un pointeur et la stocke en tant que BLOB.

Je suppose que lorsque vous modifiez la longueur, vous ne tronquerez aucun enregistrement. Si c'est le cas, alors au maximum, les données que vous convertissez en varchar (500) doivent être, au maximum, de 502 octets et ne doivent pas avoir de pointeur.

Donc, pour faire court, peu de choses devraient changer tant que vous ne tronquez aucune donnée.

DForck42
la source
5
C'est absolument incorrect. Je ne vais pas dévaloriser parce que vous l'avez testé (ce qui est plus que certaines personnes, alors merci de l'avoir fait), mais vous devez le tester à grande échelle. La réponse à laquelle vous avez lié était d'augmenter la taille et non de la diminuer. Ce sont deux opérations très différentes.
Solomon Rutzky