Transfert efficace d'une grande quantité (84 millions de lignes) de données

11

J'ai environ 84 millions de lignes. De ceux-ci, tous doivent être transférés vers une base de données distincte sur le même serveur, puis je supprime pour supprimer environ 60 millions de lignes de la base de données source.

Les 84 millions de lignes sont toutes dans le même tableau. Ce tableau représente à lui seul 90% de l'ensemble de la base de données.

Alors ... Source: 84 millions de lignes -> 24 millions de lignes Destination: 0 lignes -> 84 millions de lignes

La source exécute le mode de récupération complète, la destination sera simple.

Je me demande quelle serait la façon la plus efficace de procéder?

Plan A:

1) INSÉRER DANS la destination SELECT * FROM source

2) Source TRUNCATE

3) INSERT INTO source SELECT * FROM destination WHERE keep_condition = 1

Plan B:

1) Restaurer une sauvegarde de la base de données source en tant que base de données de destination

2) Supprimez toutes les tables sauf celle requise dans la base de données de destination

3) Source TRUNCATE

4) INSERT INTO source SELECT * FROM destination WHERE keep_condition = 1

Plan C:

1) INSÉRER DANS la destination SELECT * FROM source

2) SUPPRIMER la source OERE keep_condition = 0

ou autre chose?

Merci

elty123
la source
pourquoi n'utilisez-vous pas l'assistant d'importation et d'exportation de données? c'est un outil fourni avec l'installation de SQL Server.
Hani El Mouallem
Est-il possible de copier les 24 millions de lignes dans une nouvelle table, puis de simplement renommer les deux au besoin afin de ne jamais déplacer inutilement 84 millions de lignes?
LowlyDBA
S'agit-il d'un processus ponctuel ou en cours? Je demande parce que, étant donné le temps qu'il faudra pour traiter 80 millions de lignes, il est probable qu'il y aura des changements de données dans les lignes produisant SOURCE qui devraient maintenant vivre dans DESTINATION.
Michael Green
Cela ressemble à un problème XY: vous devez vous retrouver avec toutes les lignes de 84MM dans un DB, et 24MM de ceux dans un deuxième DB. Quelle exigence commerciale nécessite que 84MM soient déplacés et 60M supprimés, au lieu de simplement déplacer 24MM? lien: meta.stackexchange.com/questions/66377/what-is-the-xy-problem )
Pieter Geerkens
J'ai un problème très similaire et ce n'est clairement pas XY. Avant la prolifération des lois concernant la conservation des enregistrements, nous conservions toutes les données. Nous devons maintenant supprimer les lignes antérieures à la date à laquelle nous sommes légalement tenus de les conserver. Cela signifie archiver et supprimer plus de 20 ans de données, car la conservation légale dans la plupart des cas est de 7 ans. Je ne pense pas que je suis seul à croire que Microsoft est négligent de ne pas fournir la fonctionnalité de «copie en bloc» aux procédures stockées. Une application ne doit pas être plus rapide lors du déplacement de données «dans» une base de données que la base de données elle-même. L'année prochaine, une autre année doit être archivée.
bielawski

Réponses:

11

J'ajouterais que, quelle que soit votre décision, vous devrez regrouper ces transactions . J'ai eu beaucoup de chance avec l'article lié récemment, et j'apprécie la façon dont il tire parti des index par opposition à la plupart des solutions par lots que je vois.

Même très peu enregistrées, ce sont de grosses transactions , et vous pourriez passer beaucoup de temps à gérer les ramifications d'une croissance anormale des journaux (VLF, troncature, dimensionnement à droite, etc.).

Merci

Erik Darling
la source
3

"Efficace" peut s'appliquer à l'utilisation du fichier journal, aux performances d'E / S, au temps CPU ou au temps d'exécution.

J'essaierais de réaliser une opération à journalisation minimale, ce qui serait assez efficace du point de vue de la journalisation. Cela devrait vous faire gagner un peu de temps d'exécution. Si vous avez l'espace tempdb, les éléments suivants peuvent fonctionner pour vous.

CREATE TABLE #temp;
ALTER source -> BULK_LOGGED recovery model

BEGIN TRANSACTION;

    INSERT INTO dest SELECT FROM source;
    INSERT INTO #temp SELECT FROM source WHERE keep_condition=1;
    TRUNCATE TABLE source;
    INSERT INTO source SELECT FROM #temp;

COMMIT TRANSACTION;

ALTER source -> FULL recovery model
DROP TABLE #temp;

Pour qu'une opération à journalisation minimale se produise, un certain nombre de conditions doivent être remplies, notamment aucune sauvegarde en cours d'exécution, la base de données définie sur le BULK_LOGGEDmode de récupération et, en fonction de vos index, la table cible doit être vide. Certains de ces comportements ont également changé (améliorés) de SQL Server 2005 à 2008.

Là encore, sans connaître les spécificités de votre table et de vos données, n'importe laquelle de vos autres options pourrait bien fonctionner mieux. Essayez d'utiliser

SET STATISTICS IO ON;
SET STATISTICS TIME ON;

.. et voyez ce qui fonctionne le mieux.

EDIT : lorsque vous effectuez des opérations de journalisation en masse, assurez-vous de faire une sauvegarde (journal complet ou journal des transactions) avant et après l'opération si vous avez besoin d'une capacité de restauration ponctuelle et que vous soupçonnez que d'autres activités peuvent être en cours dans la base de données à en même temps que votre travail ETL s'exécute.

J'ai écrit un article de blog sur les opérations minimalement enregistrées il y a un moment, il y a des liens vers d'autres articles et de la documentation.

Daniel Hutmacher
la source
+1 pour avoir conseillé à OP de tester pour voir lequel fonctionne mieux. Bien sûr, cela pourrait être un peu difficile d'obtenir des chiffres réels à moins qu'il n'ait un système en double en développement, etc.
Max Vernon
Juste une question, que se passerait-il si vous essayez de faire une restauration ponctuelle lorsque la base de données était en mode de consignation en bloc? Je supposais que toute transaction non qualifiée de «en vrac» serait récupérable.
elty123
1
@ elty123 Dans la récupération en bloc, vous ne pouvez restaurer qu'à la fin de votre dernière sauvegarde de journal. Il n'y a aucun moment de récupération comme il y en aurait avec une récupération complète. Normalement, vous basculez vers une récupération en bloc, exécutez un processus ETL, revenez à la fin et effectuez une sauvegarde du journal.
RubberChickenLeader du
@WindRaven Ce n'est pas correct - voir ma réponse ci-dessous.
wBob
1
@wBob et @WindRaven, j'ai mis à jour ma réponse pour refléter la nécessité d'effectuer des sauvegardes avant et après l'utilisation du BULK_LOGGEDmode. Merci!
Daniel Hutmacher
1

Pourquoi pas BCP?

  1. Sauvegarder le sourcedb
  2. Remplacez sourcedb par un enregistrement en bloc
  3. Ouvrir l'invite de commande

  4. bcp server.sourcedb.table out Filename.flt -T -c

  5. bcp "SELECT * FROM sourcedb.table WHERE keep_condition = 1" queryout Filename2.flt -T -c

  6. bcp Server.destinationdb.table in Filename.flt -T -c -b1000

  7. vérifier les données

  8. Depuis SSMS Tronquez la table sourcedb
  9. bcp server.sourcedb.table in Filename2.flt -T -c -b1000
  10. Remettre le sourcedb en position pleine
stacylaray
la source
2
Parce qu'ils sont sur le même serveur. Écrire sur le système de fichiers coûterait cher. Mieux vaut créer une base de données et la présélectionner, en espérant profiter de l'initialisation instantanée des fichiers. Ce serait un choix raisonnable pour dbs sur différents serveurs, bien que SSIS soit mon premier choix s'il est disponible. NB: L'option -n (native) est plus compacte et plus sûre pour déplacer des données de SQL Server vers SQL Server. L'option -b n'a aucun effet sur la sortie bcp.
wBob
0

Ne pensez pas que vous devriez recommander de changer le modèle de récupération sans sauvegarde complète de la base de données ou sauvegarde t-log avant et après . L'une des caractéristiques du modèle de récupération BULK_LOGGED est que vous perdrez la possibilité d'effectuer une récupération ponctuelle pour les journaux T contenant des opérations enregistrées en bloc. Scénario classique: sauvegarde complète nocturne, sauvegardes t-log horaires. Vous changez le modèle de récupération en journal en bloc et démarrez votre opération. Quelque chose ne va pas et la transaction est annulée (ou vous n'en avez pas utilisé). Cependant, vous n'êtes pas sûr de ce qui se passait dans la base de données, vous devez donc restaurer à un bon point connu.

Quand pouvez-vous restaurer à nouveau? Dernière sauvegarde t-log toutes les heures qui ne contient pas d'opérations enregistrées en masse, ce qui peut entraîner la perte de n minutes de transactions. Une sauvegarde complète ou une sauvegarde t-log avant de modifier le modèle de récupération créera un point de repli. Lequel vous choisissez dépend de votre RTO.

wBob
la source
0

La suppression de partitions d'une table est un moyen très rapide et économe en ressources de supprimer de gros morceaux de données d'une table. Si cette table était partitionnée de manière à prendre en charge votre répartition source / destination, la réponse serait de restaurer une copie, de supprimer les tables et les partitions redondantes de la destination et de supprimer les partitions complémentaires de la source.

Le coût de l'activation du partitionnement peut cependant rendre cette opération plus coûteuse dans l'ensemble.

Michael Green
la source