web-dev-qa-db-fra.com

Meilleure façon de synchroniser les données entre deux bases de données différentes

Je dois implémenter la synchronisation des données entre deux grandes bases de données qui ont des structures complètement différentes. Fondamentalement, j'ai besoin de saisir des données sur les produits dans différentes tables de la première base de données et de les réorganiser pour d'autres tables dans la deuxième base de données.

Créer mes produits du premier coup n'est pas très compliqué. Mais je cherche un moyen de mettre à jour certaines données spécifiques - pas toutes les données - sur chaque produit.

Évidemment, il y a quelques problèmes qui rendent cela délicat.

  • Je ne suis pas autorisé à faire quoi que ce soit sur la base de données source, à l'exception des requêtes sélectionnées.
  • Sur la base de données cible, je peux faire des requêtes habituelles (sélectionner, mettre à jour, insérer, créer) mais je ne peux pas modifier la structure/les tables existantes.
  • Les bases de données cible et source ont des structures complètement différentes, les tables ne sont pas du tout les mêmes, donc les données doivent vraiment être réorganisées - la comparaison des tables ne fonctionnera pas.
  • La base de données cible utilise un serveur MySQL - la source peut être DB2.
  • Il n'y a aucun champ "heure de mise à jour" nulle part.

Donc, tout le processus doit être fait dans un seul script Python (idéalement).

Je pense à créer un hachage pour chaque produit, en fonction des champs à mettre à jour dans la base de données cible: md5 (code + description + fournisseur + environ 10 autres champs). Un nouveau hachage basé sur les mêmes données sera créé quotidiennement à partir de la base de données source. Je vais stocker tous les hachages dans une seule table (code d'article, current_hash, old_hash) à des fins de performances. Comparez ensuite et mettez à jour le produit si le nouveau hachage est différent de l'ancien.

Il y a environ 500 000 produits donc je suis un peu inquiet pour les performances.

Est-ce la bonne voie à suivre?

25
Neow

C'est à peu près ce que j'ai fait ou vécu ces dernières années, et mon instinct est que le temps de lire 500 000 éléments de la base de données source et de se synchroniser dans la destination ne prendra pas autant de temps qu'on pourrait le penser et le temps nécessaire pour lire les champs "clé", calculer le hachage MD5 et recouper avec votre table pour éviter de synchroniser les éléments qui n'ont pas changé ne finira pas par gagner trop de temps et peut même s'exécuter plus longtemps. Je voudrais simplement tout lire et tout mettre à jour. Si cela se traduit par un temps d'exécution trop long, je compresserais le temps d'exécution en rendant l'ETL multi-thread, chaque thread fonctionnant uniquement sur un segment de la table mais travaillant en parallèle.

Il serait important de vous assurer que votre base de données de destination possède un index de clé primaire ou un index unique. Sinon, chacune de vos mises à jour/insertions pourrait verrouiller la table entière. Ce serait mauvais si vous adoptez l'approche multithread, mais important même si vous restez monothread parce que votre travail pourrait verrouiller la table de base de données de destination et interférer avec l'application qui chevauche cette base de données.

Vous dites que la base de données source "peut être DB2". Lorsque vous dites "peut", cela signifie que la base de données est toujours en cours de conception/planification? DB2 9 ou supérieur dispose d'un suivi intégré de l'heure de la dernière mise à jour et de la possibilité d'interroger et de récupérer uniquement les éléments qui ont changé depuis un certain temps. C'est peut-être la raison pour laquelle la base de données a été conçue pour ne pas avoir de colonne indiquant la dernière heure mise à jour, par exemple:

SELECT * FROM T1 WHERE ROW CHANGE TIMESTAMP FOR TAB t1 > current timestamp - 1 hours;

La coupure d'horodatage pour la requête ci-dessus serait le dernier horodatage exécuté par votre synchronisation.

Si tel est le cas, cela devrait résoudre votre problème. Mais, votre solution finirait par être très étroitement liée à DB2 et à l'avenir, ils aimeraient peut-être passer à une autre plate-forme DB et s'attendre à ce que votre travail de synchronisation n'ait pas besoin d'être revu. Il serait donc important de vous assurer que toutes les bonnes personnes savent que votre produit dépendra de son maintien sur DB2, ou si elles prévoient de migrer, cette migration inclurait la restructuration de la base de données pour avoir une colonne "horodatage modifié en dernier" et faire tout les modifications nécessaires au niveau de l'application pour remplir ce champ.

9
Thomas Carlisle

La synchronisation des données serait bien meilleure et plus rapide, si elle pouvait se faire sur la base d'un identifiant delta ou d'un indicateur. Fondamentalement, vous devez mettre à jour les lignes de données de la base de données cible uniquement lorsqu'elles ne sont pas synchronisées avec la base de données source.

Dans la base de données SQL Server, vous pouvez également utiliser l'aide de Checksum fn pour créer l'identificateur basé sur delta.

Vous devez développer un travail basé sur SQL pour être invoqué à une certaine heure du jour ou de la nuit pour que cette logique sql soit déclenchée. . Il est préférable de l'exécuter en tant que tâche SQL nocturne, lorsque l'utilisation de la base de données est très faible. Si le delta des enregistrements source et cible ne correspond pas, extrayez uniquement ces enregistrements. Mais l'inconvénient serait de calculer la somme de contrôle des lignes de données source à chaque fois, puis de la comparer avec les données cibles.

Si vous avez une colonne comme "LastModifiedDate" dans les tables de base de données source, vous pouvez ignorer l'approche de la somme de contrôle. De cette façon, votre évaluation sera exécutée sur la colonne basée sur la date et prend moins de temps par rapport à l'approche de la somme de contrôle.

5
Karan

L'utilisation d'un hachage est une bonne idée. Puisque la sécurité n'est pas l'objectif dans ce cas, choisissez une fonction de hachage rapide (md5 est très bien).

Sauf si vous prévoyez de diviser le calcul du hachage sur plusieurs threads/processus, vous n'avez pas vraiment besoin de stocker la valeur de hachage actuelle dans la base de données. Si votre processus est un script unique, vous n'aurez que le hachage actuel en mémoire et l'écrirez dans la base de données comme l'ancien hachage après avoir mis à jour les données dans la nouvelle base de données.

1
Kent A.