web-dev-qa-db-fra.com

modifier la taille de la colonne prend très longtemps?

J'ai une table avec 45 millions de lignes (45 Go d'espace de données et 2 Go d'espace d'index). J'ai ajouté une nouvelle colonne et elle s'est terminée instantanément.

alter table T add C char(25)

Ensuite, j'ai trouvé que la taille était trop petite, alors j'ai exécuté la requête suivante.

alter table T alter column C varchar(2500)

Et cela dure une heure et fonctionne toujours. sp_whoisactive shows (pour le moment, toujours en cours d'exécution)

reads: 48,000,000
writes: 5,000,000
physical reads: 3,900,000

Cela ne devrait-il pas être vraiment rapide?

7
u23432534

En supposant que toutes les colonnes précédemment créées sont à largeur fixe comme char et datetime, l'ajout de la colonne C ci-dessus vient de l'ajouter à la fin de la section à largeur fixe de l'enregistrement ( effectivement un méta-seul changement). Cependant, sa refonte en tant que varchar a exigé qu'il soit déplacé vers la section de largeur variable de l'enregistrement, forçant une reconstruction implicite de la table. Paul Randal explique en détail les éléments internes des enregistrements dans Inside the Storage Engine: Anatomy of a Data Record .

10
MattyZDBA

J'ai testé le boîtier. Vous pouvez le faire plus rapidement en utilisant les étapes ci-dessous:

  1. Créez la même structure de table avec un nom différent (appelez-le Tbl2)
  2. Modifier la colonne sur Tbl2
  3. insérer des données de Tbl1 dans Tbl2
  4. Drop Tbl1 (l'ancienne table)
  5. Renommez Tbl2 (le nouveau) en Tbl1

Cela vous donnera de bien meilleures performances.

La raison en est que la modification de la colonne du tableau contenant des données nécessitera beaucoup de transfert de données et d'alignement des pages de données. En utilisant ma solution, vous insérez simplement des données sans réorganisation de page.

Modifier:
Dans mon test, j'ai utilisé une table avec environ 40 M lignes, une taille de table de 7 Go et une taille d'index de 2,5 Go. La méthode suggérée était de 1 minute VS 4 minutes lorsque j'ai utilisé pour renommer le champ dans la table d'origine

7
user71787