web-dev-qa-db-fra.com

Quelle est la meilleure méthode pour actualiser seulement quelques tables dans une base de données de test à partir de la production?

J'ai une très grande base de données de production et une très grande base de données d'environnement de test dans SQL Server 2008R2. Les deux bases de données ont une structure de table similaire mais des utilisateurs/connexions/autorisations/rôles différents.

Je dois actualiser périodiquement quelques tables de la base de données de test à partir de la production, environ une fois par mois.

La façon dont je prévois de le faire est

  1. Utilisez l'utilitaire BCP pour exporter les tables dont j'ai besoin depuis Production.
  2. Copiez le fichier d'exportation bcp sur le serveur de test
  3. Désactiver les index et les contraintes sur toutes les tables que je rafraîchis dans Test
  4. Tronquer les tables de base de données de test
  5. Chargez les données dans les tables de base de données de test à l'aide de BCP.
  6. reconstruire les index et réactiver les contraintes dans Test

Tout cela semble un peu trop compliqué pour une si petite tâche. Il semble également que cela générerait beaucoup de refaire (dans le t-log) Y a-t-il une meilleure façon de le faire?

Une autre façon d'y penser est de restaurer une sauvegarde de Production sur l'environnement de test - mais le problème que j'ai est qu'une sauvegarde complète serait assez volumineuse et je n'ai pas besoin de rafraîchir toutes les tables, seulement quelques- -et aussi les utilisateurs et la sécurité dans la base de données de production sont différents du test. Cela serait écrasé par les paramètres de sécurité dans la base de données de production si je restaurais la base de données entière.

12
Eric Larson

Il existe 2 méthodes adaptées à vos besoins:

(Remarque: si les tables sont référencées par une clé étrangère, vous ne pourrez pas utiliser TRUNCATE. Vous devez supprimer par blocs . Alternativement, vous pouvez supprimer tous les index + clés étrangères et charger les données, puis les recréer).

  • BCP OUT et BULK INSERT INTO destination database .

    • Assurez-vous de mettre la base de données de test en mode de récupération simple/enregistré en masse.
    • Activer l'indicateur de trace 610 - insertions journalisées minimales dans les tables indexées.

      /************************************************************************************************************************************************
      Author      :   KIN SHAH    *********************************************************************************************************************
      Purpose     :   Move data from one server to another*********************************************************************************************
      DATE        :   05-28-2013  *********************************************************************************************************************
      Version     :   1.0.0   *************************************************************************************************************************
      RDBMS       :   MS SQL Server 2008R2 and 2012   *************************************************************************************************
      *************************************************************************************************************************************************/
      
      -- save below output in a bat file by executing below in SSMS in TEXT mode
      -- clean up: create a bat file with this command --> del D:\BCP_OUT\*.dat 
      
      select '"C:\Program Files\Microsoft SQL Server\100\Tools\Binn\bcp.exe" '-- path to BCP.exe
              +  QUOTENAME(DB_NAME())+ '.'                                    -- Current Database
              +  QUOTENAME(SCHEMA_NAME(SCHEMA_ID))+'.'            
              +  QUOTENAME(name)  
              +  ' out D:\BCP_OUT\'                                           -- Path where BCP out files will be stored
              +  REPLACE(SCHEMA_NAME(schema_id),' ','') + '_' 
              +  REPLACE(name,' ','') 
              + '.dat -T -E -SSERVERNAME\INSTANCE -n'                         -- ServerName, -E will take care of Identity, -n is for Native Format
      from sys.tables
      where is_ms_shipped = 0 and name <> 'sysdiagrams'                       -- sysdiagrams is classified my MS as UserTable and we dont want it
      and schema_name(schema_id) <> 'some_schema_exclude'                     -- Optional to exclude any schema 
      order by schema_name(schema_id)                         
      
      
      
      --- Execute this on the destination server.database from SSMS.
      --- Make sure the change the @Destdbname and the bcp out path as per your environment.
      
      declare @Destdbname sysname
      set @Destdbname = 'destination_database_Name'               -- Destination Database Name where you want to Bulk Insert in
      select 'BULK INSERT '                                       -- Remember Tables **must** be present on destination Database
              +  QUOTENAME(@Destdbname)+ '.'
              +  QUOTENAME(SCHEMA_NAME(SCHEMA_ID))+'.' 
              +  QUOTENAME(name) 
              + ' from ''D:\BCP_OUT\'                             -- Change here for bcp out path
              +  REPLACE(SCHEMA_NAME(schema_id),' ','') + '_'
              +  REPLACE(name,' ','') 
              +'.dat'' 
              with (
              KEEPIDENTITY,
              DATAFILETYPE = ''native'',  
              TABLOCK
              )'  + char(10) 
              + 'print ''Bulk insert for '+REPLACE(SCHEMA_NAME(schema_id),' ','') + '_'+  REPLACE(name,' ','')+' is done... '''+ char(10)+'go' 
      from sys.tables
      where is_ms_shipped = 0 and name <> 'sysdiagrams'           -- sysdiagrams is classified my MS as UserTable and we dont want it
      and schema_name(schema_id) <> 'some_schema_exclude'         -- Optional to exclude any schema 
      order by schema_name(schema_id)
      

-

  • Méthode 2: SSIS - Ma méthode préférée dans ce cas.

    • Aucun transfert sur disque requis. Tout le traitement se fait en mémoire.
    • Vous pouvez planifier le package SSIS à l'aide du travail de l'agent SQL chaque mois pour automatiser l'actualisation des tables de PROD vers le serveur TEST.
    • Choisissez l'option " FAST LOAD "
    • Assurez-vous de choisir une bonne ligne par numéro de lot (si vous choisissez trop haut, il y aura une escalade de verrouillage - gardez-la inférieure à 5K)

Référence: The Data Loading Performance Guide et ma réponse pour - Insérer dans le tableau sélectionner * à partir du tableau vs insérer en vrac

4
Kin Shah

Il n'est pas nécessaire de faire des sauvegardes et des restaurations, ni d'appeler/coordonner des processus externes (par exemple BCP), ni même de jouer avec SSIS (très puissant, très cool, mais si je peux l'éviter, je le ferai certainement :). Vous pouvez gérer tout cela dans le confort de T-SQL, dans une procédure stockée que vous pouvez planifier via SQL Agent, ou un script que vous exécutez une fois par mois (bien que l'avoir dans un proc et une planification soit moins fastidieux à long terme) courir). Comment? En utilisant SQLCLR pour accéder à la classe SqlBulkCopy dans .NET car il s'agit essentiellement de BCP sans tout le tracas d'appeler BCP. Vous pouvez coder cela vous-même: il n'y a pas de configuration super compliquée ou quoi que ce soit car la classe SqlBulkCopy s'occupe de presque tout pour vous (vous pouvez définir la taille du lot, déclencher ou non des déclencheurs, etc.). Ou, si vous ne voulez pas jouer avec la compilation et le déploiement d'un assembly, vous pouvez utiliser une procédure stockée SQLCLR prédéfinie telle que DB_BulkCopy qui est une partie de la bibliothèque SQL # SQLCLR (dont je suis l'auteur, mais cette procédure stockée est dans la version gratuite). Je décris cela plus en détail, y compris un exemple d'utilisation de DB_BulkCopy , dans la réponse suivante:

Importer des données d'une base de données vers un autre script

S'il n'est pas clair où placer cela dans votre plan actuel, vous feriez ce qui suit:

  • Supprimez les étapes 1 et 2 (woo hoo!)
  • Remplacez l'étape 5 par un EXEC de DB_BulkCopy ou ce que vous l'appelez si vous le codez vous-même, ce qui déplace simplement les données du point A au point B.

Il convient également de noter que SqlBulkCopy et DB_BulkCopy :

  • peut accepter n'importe quel jeu de résultats: peu importe s'il s'agit d'un SELECT ou EXEC d'une procédure stockée
  • sont très faciles à mettre à jour lorsque des modifications de schéma sont apportées à l'une de ces tables; ALTER juste la requête dans votre procédure stockée qui appelle cette procédure stockée SQLCLR
  • permettre de remapper les champs, si cela est nécessaire

MISE À JOUR concernant les opérations à journalisation minimale via SqlBulkCopy

Il est possible d'obtenir un nombre minimal d'opérations enregistrées, mais vous devez savoir:

  • Vous devez utiliser l'option TableLock Bulk Copy
  • Pour les tables avec des index clusterisés, cela chargera d'abord les données dans [tempdb] puis faites l'insertion ordonnée dans la destination. Par conséquent, une charge supplémentaire est encourue, à la fois en termes d'E/S physiques vers tempdb (fichiers de données et journaux) ainsi que l'opération de tri (en raison de ORDER BY qui est nécessaire pour obtenir les opérations enregistrées de façon minimale)
  • Quelques résultats de tests ici: Livre blanc: performances de SqlBulkCopy
  • Quelques résultats de test ici: Dépannage de SqlBulkCopy ne faisant pas de journalisation minimale
3
Solomon Rutzky