Ajout de colonnes aux tables de production


28

Quelle est la meilleure façon d'ajouter des colonnes à de grandes tables de production sur SQL Server 2008 R2? Selon les livres en ligne de Microsoft:

Les modifications spécifiées dans ALTER TABLE sont implémentées immédiatement. Si les modifications nécessitent des modifications des lignes du tableau, ALTER TABLE met à jour les lignes. ALTER TABLE acquiert un verrou de modification de schéma sur la table pour s'assurer qu'aucune autre connexion ne référence même les métadonnées de la table pendant la modification, à l'exception des opérations d'index en ligne qui nécessitent un verrou SCH-M très court à la fin.

(http://msdn.microsoft.com/en-us/library/ms190273.aspx)

Sur une grande table avec des millions de lignes, cela peut prendre un certain temps. Prendre une panne est-il la seule option? Quelle est la meilleure façon de gérer ce genre de situation?


1
Article récent concernant ce problème: sqlservercentral.com/articles/Change+Tracking/74397
8kb

Réponses:


27

"Ça dépend"

Si vous ajoutez une colonne qui ne nécessite pas l'ajout de données aux lignes, cela peut être assez rapide.

Par exemple, l'ajout d'un entier ou d'un caractère nécessite des mouvements physiques de ligne. L'ajout d'un varchar nullable sans défaut ne devrait pas (sauf si le bitmap NULL doit être développé)

Vous devez l'essayer sur une copie de production restaurée pour obtenir une estimation

Créer une nouvelle table, copier, renommer peut prendre plus de temps si vous devez rajouter des index et des clés sur une table de milliards de lignes.

J'ai changé des milliards de tables de lignes qui ont pris quelques secondes pour ajouter une colonne nullable.

Ai-je dit de faire une sauvegarde en premier?


2
+1 sur la sauvegarde. et assurez-vous que vous disposez également de suffisamment d'espace journal.
SqlACID

Pouvez-vous expliquer pourquoi l'ajout d'un int ou d'un caractère nécessite des mouvements physiques de ligne?
sh-beta

5
Vouliez-vous dire "ne nécessite pas" l'ajout de données aux lignes de votre deuxième ligne?
Ben Brocka

21

Si la colonne est NULLable, l'impact doit être négligeable. Si la colonne ne peut pas être NULL et que la valeur doit être définie, cela peut être très différent. Ce que je ferais dans ce cas est, au lieu d'ajouter une contrainte non nulle et par défaut en une seule fois, d'ajouter efficacement des données à chaque ligne:

  • ajouter la colonne comme NULLable - devrait être rapide dans la plupart des cas
  • mettre à jour les valeurs par défaut
    • vous pouvez le faire par lots si nécessaire
    • vous pouvez également l'utiliser pour appliquer une logique conditionnelle où certaines lignes peuvent ne pas obtenir la valeur par défaut
  • ajouter les contraintes non nulles / par défaut
    • ce sera plus rapide lorsqu'aucune des données n'est NULL, mais devrait toujours être mesurable

Convenez avec @gbn que vous pouvez tester cela en restaurant une copie de la production et en l'essayant là ... vous aurez une bonne idée du timing (en supposant que le matériel est quelque peu similaire) et vous pouvez également voir l'impact sur le journal des transactions.


Concernant le dernier morceau: •add the not null/default constraintsje ne suis pas sûr qu'il n'y ait pas de problème potentiel avec cela ... Lorsque MSSQL (même 2008R2) change une colonne non nulle en null, si vous mettez une trace dessus, vous pouvez la voir réellement sous les couvertures faire une mise à jour complète de chaque ligne du tableau, c'est-à-dire que update table1 set column1 = column1je suppose qu'il fait la vérification non nulle d'une manière complètement idiote. Cette transaction est deux fois la taille de la table (avant et après les pages), donc pour une table DW peut être énorme. Auparavant, nous devions extraire les données bcp, les tronquer, effectuer des modifications nulles à non nulles, puis les

Si quelqu'un connaît un moyen de contourner cela, j'aime savoir ... En revanche, dans Oracle, changer null en non null fait un verrou, puis une sélection pour vérifier qu'il n'y a pas de null, puis une mise à jour instantanée de métadonnées purement.

Hé @Mike, cela ressemble à une bonne question potentielle à part entière.
Derek Downey

4

Avez-vous envisagé:

  1. Création d'une nouvelle table qui inclut les modifications apportées à la définition de table.
  2. Insertion dans la nouvelle définition de table en sélectionnant dans la table d'origine.
  3. Renommer la table d'origine en _orig, puis renommer la nouvelle table en son nom d'origine.

L'inconvénient ici est que vous devez avoir suffisamment d'espace dans la base de données pour effectuer cette modification. Vous pouvez toujours avoir besoin d'un verrou de lecture sur la table pour éviter toute lecture sale.

Cependant, vous minimisez l'impact sur les utilisateurs finaux s'il existe une possibilité ou un besoin d'accéder simultanément à la table d'origine. Il devrait également minimiser les durées de verrouillage.


N'auriez-vous pas besoin d'un verrou en écriture plutôt que de lire? C'est bien pour les utilisateurs de voir les données dans l'ancienne table, vous ne voulez tout simplement pas qu'ils commettent des modifications qui seraient écrasées lorsque vous auriez terminé l'échange de tampon.
Jon of All Trades,

C'était ma pensée avec mon chapeau d'entrepôt de données sur où les changements peuvent être contrôlés un peu plus facilement. Dans une situation OLTP, vous avez raison, un verrouillage en écriture serait nécessaire pour éviter que des modifications soient apportées à la table.
RobPaller
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.