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

12

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 n'ai besoin de rafraîchir que quelques tables de la base de données de test périodiquement depuis la production, environ une fois par mois.

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

  1. Utilisez l'utilitaire BCP pour effectuer une exportation des 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. Rechargez les données dans les tables de la 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 pour moi de le faire 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 restaure la base de données entière.

Eric Larson
la source
Cette approche pourrait également être étudiée: sqlperformance.com/2012/08/t-sql-queries/… et sqlperformance.com/2013/04/t-sql-queries/…
Aaron Bertrand

Réponses:

4

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 les utiliser TRUNCATE. Vous devez les supprimer par blocs . Vous pouvez également supprimer tous les index + clés étrangères et charger les données, puis les recréer).

  • Base de données de destination BCP OUT et BULK INSERT INTO .

    • 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: Le Guide de performances de chargement de données et ma réponse pour - Insérer dans le tableau sélectionnez * à partir du tableau par rapport à l'insertion en bloc

Kin Shah
la source
1
SSIS est certainement la voie à suivre ici. Le pompage de données est ce qui a été conçu pour faire.
Steve Mangiameli
3

Il n'est pas nécessaire de faire des sauvegardes et des restaurations, ni d'appeler / coordonner des processus externes (c'est-à-dire 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 SqlBulkCopyclasse 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 soitSqlBulkCopyLa classe 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 fait partie de la bibliothèque SQL # SQLCLR (dont je suis l'auteur, mais qui est 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!)
  • Remplacer l' étape 5 avec un EXECde DB_BulkCopy ou tout ce que vous appelez si vous le code vous - même, qui se déplace uniquement les données du point A au point B.

Il convient également de noter que SqlBulkCopyet 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 de copie en bloc de TableLock
  • Pour cela, pour les tables avec des index clusterisés, chargez d'abord les données dans [tempdb], puis effectuez l'insertion ordonnée dans la destination. Par conséquent, il y a une charge supplémentaire encourue, à la fois en termes d'E / S physiques vers tempdb (données et fichiers journaux) ainsi que l'opération de tri (en raison de ce ORDER BYqui est requis pour obtenir les opérations journalisées minimales)
  • 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
Solomon Rutzky
la source