Ce diaporama a bien été signalé.
Le téléchargement de votre SlideShare est en cours. ×

Importer 500 millions de données de MySQL vers Neo4j

Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Prochain SlideShare
Neo4j en15 minutes
Neo4j en15 minutes
Chargement dans…3
×

Consultez-les par la suite

1 sur 60 Publicité

Plus De Contenu Connexe

Similaire à Importer 500 millions de données de MySQL vers Neo4j (20)

Plus récents (20)

Publicité

Importer 500 millions de données de MySQL vers Neo4j

  1. 1. Comment importer 567 273 969 épisodes vus (et plus) de MySQL vers Neo4j 😱
  2. 2. @tentacode chez @betaseries
  3. 3. BetaSeries en chiffres • 10 ans d'activité • 1 036 351 membres • 16 848 séries TV • 12 244 361 séries suivies • 237 811 épisodes vus par jour • 567 millions d'épisodes vus depuis 10 ans 😱😭🔫 • plus les notes, commentaires, téléchargements etc.
  4. 4. BetaSeries Insights • Utiliser la richesse et le volume des données de BetaSeries. • Vendre ces données aux pros des médias (producteurs, diffuseurs, journalistes etc.). • Analyse d'audience en temps réel. • Permettre des analyses et comparaisons complexes : “ Est-ce que Game of Thrones marche mieux que The Walking Dead chez les moins de 30 ans qui regardent aussi Big Bang Theory ? ”
  5. 5. Le choix de la BDD (source : Dilbert par Scott Adams)
  6. 6. Pourquoi Neo4j ? • C'est assez simple à mettre en place, à interroger et à maintenir (cypher 😍). • Les bases en graphes permettent de modéliser facilement un schéma qui évolue. • C'est très performant quand on travaille sur des petits sous ensembles du graphe (une série en particulier ou un type d'audience). • Ça s'intègre très bien avec PHP : graphaware/ neo4j-php-client
  7. 7. Les deux spécificités du projet BetaSeries Insights
  8. 8. #1. Chaque jour des statistiques figées sur les données depuis le début de BetaSeries jusqu'à la journée de la veille.
  9. 9. Avantages • On peut récupérer le différentiel des données une fois par jour (via un cron). • Une fois une statistique calculée, on peut la mettre en cache pour la journée (on utilise un cache Redis). • Il n'y a pas un grand besoin de performances en écriture, puisqu'on écrit plus dans Neo4j. • Il n'y a pas non plus besoin de performances en lecture, puisque tout est en cache (sauf au premier calcul du jour sur une statistique donnée).
  10. 10. #2. On a besoin régulièrement d'importer le total des données de BetaSeries.
  11. 11. Pourquoi ? • BetaSeries est complexe, on peut avoir des problèmes de fiabilité des données importées qui demandent un ré-import. • Le projet Insights est jeune et évolue vite, on doit rajouter des statistiques régulièrement, dont des nouveaux types de noeuds et relations. • Il fallait bien importer les 10 ans de données une première fois quoi qu'il arrive. • C'est une sécurité supplémentaire de pouvoir recréer complètement la BDD en cas de panne.
  12. 12. L'infrastructure de
 BetaSeries Insights
  13. 13. • Le serveur MySQL est répliqué sur plusieurs slaves. • Sur le serveur physique d'Insights on retrouve un slave dédié, un serveur Neo4j et une base Redis. • Le slave est utilisé pour récupérer les données pendant l'import. • Mais aussi pour récupérer des metadonnées de BetaSeries (nom, description, images des séries etc.).
  14. 14. Insights V1 “Les fichiers CSV : la méthode de grand-père.” — Sylvain Roussy
  15. 15. Insights V1 • ma connaissance de Neo4j qui se réduisait à la doc. • l'utilisation d'une machine non dédiée et limitée en ressources. • une approche d'export / import non appropriée au volume des données. Le premier “Proof of Concept” d'Insights était limité par :
  16. 16. Exemple de données SQL La table shows qui contient les séries TV
  17. 17. Export de MySQL vers CSV • Première approche : un script PHP par noeud ou relation qui fait la requête SQL et qui génère le fichier CSV. • Plus performant : directement générer le fichier CSV avec SELECT INTO OUTFILE.
  18. 18. Résultat un joli fichier CSV
  19. 19. Importer dans Neo4j • Ne pas oublier de renseigner la configuration du dossier d'import dbms.directories.import=/tmp • On utilisera Cypher avec
 LOAD CSV WITH HEADERS • On créé le noeud Show correspondant en faisant bien attention aux types des données (tout est une chaîne dans un CSV)
  20. 20. Même principe pour les relations • On commence à avoir un temps d'export plus long (60 secondes pour 12M de lignes) et un CSV plus lourd (190 mo) • On peut gzip le fichier pour gagner de la place (36 mo), mais ça prends un peu de temps.
  21. 21. Les ennuis commencent 😩 • On a déjà bien du mal à importer 1M de lignes dans Neo4j (4 minutes). • Si on utilise pas USING PERIODIC COMMIT on explose la RAM de Neo4j. • On va devoir faire un import par lot (12 imports, 1 million de lignes à la fois).
  22. 22. Interlude SQL 🤔 Savez-vous comment paginer correctement une requête SQL ?
  23. 23. Pas avec LIMIT et OFFSET 👎 • Mettons qu'on veuille récupérer 1 million d'épisodes vus, à partir du 500 millionième vu, la requête prend 18,7 secondes à s'exécuter. • Plus la table est grosse et plus on va avancer dans l'OFFSET, plus la requête sera longue.
  24. 24. En passant par un index 👍 • En passant par un index on passe à 95 ms ! • Il faut donc calculer les bornes pour chaque passage du traitement par lot. • (on peut tricher sur les id)
  25. 25. Et notre import total ?! 🙌 On l'aurait presque oublié.
  26. 26. Neo4j import tool Ça a un peu changé depuis, mais à l'époque c'était ça.
  27. 27. C'est bien, mais pas top. • C'est pratique, on peut utiliser presque les mêmes CSV. • Les metadonnées doivent être dans les headers, il faut donc changer le header de chaque CSV. • L'import ne peut se faire que sur une base éteinte, il faut couper neo4j pendant l'import. • Pas hyper clair au niveau de la tolérance aux fautes.
  28. 28. Et nos 567 millions d'épisodes vus ? J'aurais préféré les oublier. 😭
  29. 29. Pas possible. ☠ • En faisant une extrapolation à partir de l'export / import des 12 millions de relations des séries suivies... • On arrive à 47 minutes d'export, un fichier CSV de 9go (difficilement gzipable) et un import de 37,8 heures ! 😨 • Sans compter le serveur Neo4j de la V1 qui n'aurait probablement pas tenu la charge des 567 millions de relations.
  30. 30. Pour réduire le volume des données à importer on n'importe pas le détail des actions (type épisodes vus) comme une relation, mais on dénormalise sur une propriété countWatched du noeud Episode. (il y a une perte d'information)
  31. 31. Le schéma V1
  32. 32. La dénormalisation sur Episode
  33. 33. Insights V1 en résumé
  34. 34. Problème 😡 Impossible d'avoir ce genre de statistiques avec la dénormalisation.
  35. 35. Conclusion : Avantages du CSV • C'est universel.
  36. 36. Insights V2 l'import massif des données
  37. 37. On veut conserver l'intégralité des données des actions, dont la relation
 (:Person)-[:WATCH]->(:Episode)
  38. 38. Rappel : le schéma V1
  39. 39. Le schéma V2
  40. 40. Quand on sait pas faire… on demande à ceux qui savent.
  41. 41. Amélioration de l'import journalier avec apoc • apoc est un ensemble de procédures pour Neo4j. • apoc possède de nombreuses procédures d'accès aux données (JSON, XML et... JDBC !) • import / export deux en un et optimisé, parfait pour notre export journalier.
  42. 42. Un petit échauffement 💪
  43. 43. Toujours pas suffisant pour un import total… wait for it
  44. 44. 😱 Java 😱
  45. 45. L'API BatchInserter • L'API BatchInserter est le moyen le plus performant pour créer une base de données Neo4j à partir de zéro. • Elle est contenue dans l'API Java de Neo4j. • Un nouveau fichier graph.db est directement créé sur le filesystem. • On peut aussi travailler sur un fichier graph.db existant (base éteinte), mais ce n'est pas mon cas.
  46. 46. Création de l'importer
  47. 47. Création de noeuds et de relations
  48. 48. ⚠ ne pas oublier ⚠ • Bien penser à couper la réplication du Slave MySQL pendant l'import. • Une fois le fichier graph.db créé dans un dossier temporaire on coupe neo4j, on fait un backup du fichier graph.db actuel et on le remplace par le nouveau fichier. • Bien penser à mettre les droits neo4j:adm en récursif sur graph.db • Relancer neo4j. • Exécuter des scripts post import. • Warmup les données comme pour l'import journalier.
  49. 49. Scripts post import
  50. 50. Insights V2 en résumé
  51. 51. V1 -> V2 • Nombre de noeuds : 2.3M -> 18M : +680% • Nombre de relations : 13M -> 650M : +4900% • Nombre de propriétés : 18M -> 640M : +3450% • Taille du store : 1.8gb -> 46gb : +2440%
  52. 52. À propos du page cache • Pour de meilleurs performances, il faut que tout le store soit contenu dans le page cache (et donc en RAM) :
 
 dbms.memory.pagecache.size=64g • Après avoir relancé le serveur (typiquement après un import total) il faut bien penser à warmup le page cache.
 
 CALL apoc.warmup.run(true);

  53. 53. Le futur d'Insights 🚀 • Pas trop de changement dans le schéma de base. • Mais des données évolutives dans Neo4j (classements, cibles, etc.). • Des stats comparatives entre séries, pool de séries, cibles, etc. • De l'analyse prédictive. • De l'analyse sémantique. • Un moteur de recommandation pour BetaSeries ?
  54. 54. Conclusion bateau 🚤 • Il faut toujours utiliser les outils adaptés pour résoudre un problème. 🛠 • Quitte à se faire un peu violence. 😡 • À condition de les connaître bien sûr. 🙃
  55. 55. Des questions ?

×