2010-09-13 5 views
5

J'ai un produit de transformation de données, qui permet de sélectionner des tables dans une base de données et de transformer les données de ligne de la base de données source en base de données de destination.Comment gérer d'énormes transactions sur n'importe quelle base de données?

Ceci est géré dans le produit actuel (table de travail et moteur Java) en traitant 1000 lignes à la fois et en effectuant 10 lignes en parallèle. Cette approche fonctionne correctement sur les ensembles de données plus petits. Mais, quand je dois transformer d'énormes ensembles de données (dire au sujet de X millions de disques) à un moment - cette approche fonctionne toujours, mais

  • La CPU de la machine hôte sur laquelle mon produit fonctionne, est sous forte charge.
  • La base de données source et la base de données cible sont perforées avec un trop grand nombre de transactions qu'elles commencent à ralentir. (Maintenant, cela peut être dû au fait que le serveur de base de données tourne probablement sur un matériel plus lent.)

J'ai commencé à chercher des solutions et j'ai rapidement répondu à cette question en demandant un matériel "sur les machines du serveur de base de données source/destination. Cela impliquait, par exemple, d'acheter un nouveau CPU multi-core et de la RAM supplémentaire. Il s'avère que la mise à niveau du matériel n'était pas la seule préoccupation: il fallait acheter plusieurs licences logicielles pour la base de données - grâce à des processeurs multicœurs (licence par cœur).

Donc, la balle est dans mon camp maintenant, je vais devoir trouver des moyens de résoudre ce problème, en apportant des modifications à mon produit. Et, voici où j'ai besoin de votre aide. En ce moment, je ne pouvais penser à une approche possible pour la manutention des charges énormes:

Approach1

  1. Lecture des données de base de données source, il persiste à un support temporaire (fichier).
  2. Transformez des données dans un fichier persistant, en l'exécutant dans un environnement distribué (machines monotouches moins chères), en gérant le "compromis" de basculement vers la persistance de fichier. (Utilisation de quelque chose comme Apache Hadoop pour gérer la partie de calcul répartie)
  3. Ecriture de données dans une base de données de destination.

C'est tout ce que j'ai pu trouver pour l'instant, d'un point de vue architectural. Avez-vous déjà géré cette situation? Si oui, comment l'avez-vous géré? Appréciez vos suggestions et votre aide.

+0

Quel est le goulot d'étranglement? Vous avez mentionné deux candidats: la charge de l'application et la charge de la base de données. Pouvez-vous l'affiner davantage? – oksayt

+0

@oksayt En ce moment, ma principale préoccupation est le chargement de la base de données. Je n'ai pas de repères à ce sujet, mais l'idée est de construire un meilleur produit, en tenant compte des goulots d'étranglement possibles. – Jay

Répondre

3

Il y a quelques choses que vous pourriez faire sans augmenter le coût de la licence de base de données:

  • Votre outil met la CPU sous une charge lourde, en supposant que votre outil est en cours d'exécution sur une machine qui ne exécuter une base de données, augmenter la puissance du processeur sur cette machine, ou si votre outil le permet, l'exécuter sur plusieurs machines.
  • L'une des raisons pour lesquelles le nombre de transactions actives augmente est que chaque transaction prend du temps. Vous pouvez accélérer cela en optimisant vos disques ou en mettant des disques plus rapides.

De plus, si vous utilisez un insert au lieu d'un insert en vrac, il existe un potentiel d'amélioration considérable. Le problème avec l'insertion normale est qu'il écrit des informations dans les journaux afin qu'il soit possible d'annuler la transaction.

Dans this cas où je serais en mesure d'aider quelqu'un à réduire le temps de chargement de 10 heures à 6 minutes :)

+0

+1 définitivement insert en vrac si son utilisation n'est pas un gain énorme. – eglasius

+0

vous remercie pour le lien vers l'étude de cas. Mon intention en posant cette question était de rassembler toutes les solutions possibles à mon problème. Je ne veux pas que vous vous inquiétiez trop des transactions de la base de données. Si vous pouviez considérer l'informatique distribuée comme l'une des solutions possibles, voteriez-vous pour une telle solution? Si non, quels sont les moyens non-base de données possibles à ce problème? – Jay

+0

Au lieu d'utiliser une base de données relationnelle locale, vous pouvez utiliser un magasin de données de paire de valeurs de nom de cloud, mais votre goulot d'étranglement sera alors votre connexion Internet. Vous pouvez également démarrer plusieurs instances de machine lorsque vous exécutez l'importation et les arrêter lorsque l'importation est terminée. –

0

La première chose à considérer ici est si vous avez vraiment besoin de transactions pour cette quantité de données. Si la réponse est non, votre produit de base de données a probablement une option d'insertion en bloc qui est faite pour ce type d'insertion de base de données volumineuse. Editer (suite aux commentaires): Je pense que le plus gros pour votre argent (dans SQL Server de toute façon) serait de définir la base de données cible en mode de récupération simple pour la durée de l'opération. En fait, si vous l'avez fait, il est probable que vous n'ayez pas à apporter d'autres modifications au code.

Toutefois, cela n'est approprié que si la base de données cible n'est pas utilisée pour d'autres tâches en même temps. Je dirais que c'est une exigence fondamentale. C'est une erreur de base de données fondamentale d'essayer d'insérer 25 millions d'enregistrements dans une base de données pendant qu'elle est en ligne avec des transactions OLAP. Si cela est strictement nécessaire, je pense que la solution est de rendre le processus très lent (avec des pauses importantes) afin de libérer des ressources afin que les bases de données puissent continuer à fonctionner.

+0

Vous suggérez que si je devais ignorer les transactions et trouver un moyen d'utiliser l'option d'insertion en masse qui est généralement disponible pour la base de données, cela n'affecterait pas la charge sur la base de données? Ainsi, si vous insériez 25 millions d'enregistrements, en utilisant un utilitaire d'importation, les performances de votre base de données pour toutes les demandes en cours de traitement ne seraient pas affectées? Si oui, avez-vous des références disponibles dans ce contexte? – Jay

+0

Je ne dirais pas qu'ils ne sont pas affectés, mais l'opération est optimisée pour ce qu'elle fait. Je vois que vous essayez d'utiliser à la fois Oracle et SQLServer. Vous pouvez essayer le support JDBC pour les opérations en bloc, mais je ne suis pas sûr exactement ce que fait le pilote. Voici une documentation pour optimiser les insertions en vrac dans SQL: http://msdn.microsoft.com/en-us/library/ms190421%28v=SQL.105%29.aspx – Yishai

+0

merci pour le lien, je vais le vérifier . – Jay

0

l'avez-vous comparé en utilisant des transactions de plus petite taille? sinon, je n'utiliserais pas de transactions pour cela. de votre problème de licence semble que vous utilisez un serveur Oracle ou SQL. les deux ont une capacité d'insertion en masse, ce qui serait mieux adapté à cela que les transactions.

+0

non, je ne l'ai pas référencé, ou plutôt, il a été benchmarké, c'est juste que je n'ai pas les statistiques en ce moment. Oui, j'ai testé mon produit à la fois contre Oracle et SQL Server. Je suis conscient du fait qu'ils ont des utilitaires d'importation/exportation, mais la question est, quelle est leur efficacité? – Jay

+0

ils peuvent être très efficaces. Je les ai utilisés avec un serveur sql il y a des années pour déplacer et traiter des millions d'enregistrements dans une base de données de rapports chaque nuit. Le processus a pris environ 3 heures, mais il y avait une énorme quantité de prétraitement qui devait être fait sur chaque enregistrement. – scphantm

1

Diviser pour mieux régner!

Si la source DB ne peut pas gérer deux tâches à la fois (l'ETL et les transactions « ordinaires »), alors ne font pas souffrir:

  • Copiez les données source à un « miroir ».
  • Effectuez l'ETL sur le "miroir".

NB - quand je dis « miroir » Je veux dire simplement une copie qui permet et la copie rapide efficace des données (un peu comme une « mise en scène » DB) - pas un autre gros/processus ETL lent/méchant . L'idée ici est d'optimiser le processus au profit de la base de données source. Ensuite, vous pouvez optimiser l'ETL vers le DB cible pour bénéficier du DB cible; parce que vous avez mis la source et la cible à part, il sera plus facile d'optimiser les parties de lecture/insertion du processus global.

Vous pourriez probablement faire une chose similaire à la fin de la cible aussi (en utilisant un autre "miroir"/staging DB).

Cette approche n'est pas si différente de ce que vous avez suggéré, mais je suppose qu'en copie directe des données entre deux db identiques du le même type sera à la fois le plus facile à gérer et le plus efficace. Après cela, vous pouvez commencer à appliquer certaines des autres suggestions que d'autres peuvent mettre en avant.

Une dernière chose - vous pourriez expérimenter avec l'outil ETL - si vous utilisez

0

utiliser l'oracle sql chargeur (import/export). importez les données dans une table intermédiaire et une fois que tout se passe bien, renommez la table en tant que table principale après avoir renommé la table principale en tant que sauvegarde. N'oubliez pas que vous devez appliquer les contraintes uniquement après chaque importation/téléchargement.Vous pouvez appeler le chargeur SQL à partir du programme Java.

Questions connexes