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
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.
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 .
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.
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
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:
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 :
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:
[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)