web-dev-qa-db-fra.com

Ajout de colonnes aux tables de production

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 de la table, 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?

29
sh-beta

"Ç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 de ligne physiques. 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?

27
gbn

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
  • ajoutez 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.

21
Aaron Bertrand

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.

4
RobPaller

J'ai une exception spéciale qui, à mon avis, devrait être mentionnée.

Avec SQL Server 2012 Enterprise et versions ultérieures, l'ajout d'une nouvelle colonne NOT NULL avec une constante d'exécution est une opération en ligne qui se termine instantanément et ne dépend pas de la nombre de lignes dans le tableau.

Vous trouverez plus d'informations à ce sujet dans MSDN

Je vais reproduire la section importante

À partir de SQL Server 2012 (11.x) Enterprise Edition, l'ajout d'une colonne NOT NULL avec une valeur par défaut est une opération en ligne lorsque la valeur par défaut est une constante d'exécution. Cela signifie que l'opération est terminée presque instantanément malgré le nombre de lignes du tableau. Parce que, les lignes existantes dans la table ne sont pas mises à jour pendant l'opération. Au lieu de cela, la valeur par défaut est stockée uniquement dans les métadonnées de la table et la valeur est recherchée, selon les besoins, dans les requêtes qui accèdent à ces lignes.

1
rince