De MariaDB à MongoDB ep4 : Script final, réflexions

closeCet article a été publié il y a 9 ans 3 mois 21 jours, il est donc possible qu’il ne soit plus à jour. Les informations proposées sont donc peut-être expirées.

Après avoir réfléchi, lu, bricolé, expérimenté, pour migrer une base de MariaDB vers MongoDB, il restait un bémol à traiter : les performances. En effet, on a fait les tests sur 4 films, et j’en ai personnellement plus de 440 (441 d’après mon application en l’état). Et il faut donc trouver une méthode qui permettra de passer aussi à plus gros, même au-delà de mon cas, s’il on veut arriver premier sur le podium. Et on n’échappera pas en conclusion à quelques réflexions sur cette migration. N’est-ce pas un bon moyen de finir l’année ?

Parcourir de grosses tables : exit fetchall()

Le problème de fetchall(), c’est qu’il convertit la totalité des résultats dans un tuple, qui va prendre une place monstrueuse en mémoire, et pourrait s’avérer lent au possible. Je vais donc plutôt passer par fetchone(), et parce que j’ai eu un souci avec la boucle for lorsque j’ai essayé de l’utiliser, j’ai décidé d’utiliser une boucle while à la place. Quelques erreurs plus tard (notamment à cause de Sacré Graal dont l’accent aigu n’était pas enregistré correctement par MariaDB, et donc impossible à convertir pour Python), et le tour était joué.

J’ai donc une version finale fonctionnelle de mon script migrate.py. J’ai tenté d’ajouter quelques commentaires utiles, et on détaillera le fonctionnement après :

J’en ai profité au passage pour renommer voire carrément supprimer des variables. Ma requête SQL permet maintenant de sélectionner tous les films de la table collect_liste_films. Et la boucle while, à laquelle on se prépare avec un premier fetchone(), qui fait au final le même boulot. Pour les débutants en Python (mais ça existe dans d’autres langages, même le vénérable BASIC), ça signifie « tant que la condition est remplie ». La condition, c’est « y-a-t-il quelque chose dans film ? » après fecthone(), qui renvoie None quand il n’y a plus rien. Donc tant qu’il y a quelque chose (un film en l’occurrence), il fait le traitement (ajout/modification/suppression des clés, puis insertion dans MongoDB).

Avec time, j’ai mesuré que la conversion des 441 films a pris à peine une demi-seconde, également réparti entre « user » et « system » (ce dernier critère prend en compte l’écriture sur disque). Vérification avec le shell mongo :

Voilà, maintenant, le vrai travail commence.

Réflexions sur le script, et sur la nouvelle base

J’avais prévenu, le script reste très basique, et pas seulement parce qu’il n’a permis de traiter qu’une base de données simple. Si la base de données MySQL est effectivement « sécurisée » par un couple utilisateur/motdepasse, ce n’est pas le cas de MongoDB par défaut. Rien de transcendant, mais dans un environnement plus évolué (multi-serveurs, ou avec tout ça embarqué dans du container Docker, par exemple).

Comme j’ai dit, j’ai eu droit à une sale erreur sur l’encodage de caractères sur l’un des films (que mon application PHP m’a confirmé, affichant un joli ? en lieu et place de l’accent aigu attendu), qui a entraîné l’interruption du script, je n’avais alors que 385 films sur les 441 de transférés. Je n’ai pas abordé cet aspect, qui pourrait s’avérer conséquent suivant l’âge et la taille de la base. D’ailleurs, c’est pas beau quand ça plante (ça encourage vraiment à ne pas les voir ces erreurs, je trouve) :

Les tenanciers du forum NextINpact en ont fait les frais, avec des données dans plusieurs encodages différents, remontant parfois à près de dix ans. En écrivant ce billet, j’ai essayé de retrouver le message du mécano qui s’occupait de mettre à jour la base de données, c’est édifiant :

mariadb-mongodb-utfconv

Et maintenant, je vais devoir faire un vrai boulot sur l’API, en tenant compte des différences, sur la gestion de l’ObjectId qu’est devenu l’id des films, sachant que je n’ai plus besoin de jointures entre collections qui n’existent plus, et sur d’autres choses. Donc mon application PHP (qui sera évidemment la première à bénéficier de l’API, suis pas fou) devra être partiellement revue, sur l’accès et la manipulation des données, qui passera dès lors par l’API. Rien d’insurmontable, et en plus ça permettra de supprimer quelques fonctions de base qui de toute façon n’ont jamais été mise en pratique, ou qui demanderont d’être adaptées de toute façon (la gestion des types de films étant réintégrée directement au sein des documents). Je vais devoir gérer la recherche différemment, et à l’inverse de MariaDB je vais probablement devoir définir un index sur le titre. Bref l’évolution du schéma n’est pas terminée.

J’aurais très bien pu me sortir les doigts et coder mon API directement sur MariaDB. MongoDB s’accompagne de concepts différents qui sont encore nouveaux pour moi, les versions récentes de la base ont des fonctions intéressantes mais que je n’utiliserais pas pour le moment, car je vais rester sur une base Wheezy quelques temps encore, vu mes difficultés avec CentOS, et il va me manquer notamment la recherche « full text », ce qui va me faire mal, très mal je pense sans MongoDB 2.4 (obligation de passer par une des bêtes noires de la majorité des développeurs, les expressions régulières). Une aventure qui m’exciterait presque si j’étais déviant.

Et là, ça me permet de rebondir, en guise de conclusion, sur le piège que pourrait constituer cette conversion. Tous les modèles de données existants ne pourront pas être modifiés pour s’adapter à MongoDB et son classement en collection de documents et son stockage BSON (du JSON aux hormones). Lors de la création d’un nouveau schéma, les possibilités sont multiples, mais vont dépendre de la quantité d’informations nécessaire, de leur fréquence, et, il faut le dire, des objectifs à remplir derrière en terme d’accès à ces données. Vous pourriez au final vous retrouver avec une situation où le gain de code ou de performance est nul (ce qui pourrait être fait avec une seule requête SQL prendrait plusieurs requêtes MongoDB, ou inversement), voire l’inverse. Bref, MongoDB n’est pas non plus magique, et ne résoudra pas nécessairement les problèmes de performance que vous pourriez avoir à l’heure actuelle. Mais c’est un dispositif qui a déjà trouvé sa place au sein de plusieurs structures, tel le vénérable Sourceforge, ou le réseau social orienté professionnels LinkedIn. Mais les petits projets aussi peuvent en profiter dont le mien dans un futur plus ou moins proche.