legi.py
legi.py copied to clipboard
Adaptation du schéma de données pour MySQL
Pour faciliter la conversion de la bdd SQLITE en format MySQL
À vrai dire je n'aime pas beaucoup l'idée de dégrader le schéma SQL pour se conformer aux limitations de MySQL.
J’aimerais bien aussi que ça puisse être disponible pour MySQL ; à l’utilisation, la base SQLite est assez lente sur mon ordinateur (là, je viens de lancer la recherche des articles d’une section et en attendant j’écris ce message) et je pense bien que MySQL ne souffrirait pas de telles lenteurs.
Sur le changement du schéma, c’est somme toute assez mineur, et vu les avantages procurés (Pierre pourrait utiliser legi.py après conversion du SQLite -> MySQL, et possibles/probables gains de vitesse) le ratio coûts/bénéfices me semble fortement positif.
Sur les coûts, il y a surtout le changement pour les bases existantes. Mais il est possible qu’il n’y ait pas besoin de les changer, seulement les nouvelles intègreraient ce nouveau schéma.
Je suis (encore) en train de travailler sur legi.py+Archéo Lex (j’avais pas beaucoup avancé). J’essaye de tester aujourd’hui :
- ce patch sur une nouvelle base
- ce patch sur une base actuelle
Je doute que tu obtiennes un fort gain de performance simplement en changeant de moteur SQL. Si une requête prend beaucoup de temps c'est pour deux raisons:
- elle n'utilise pas un index
- les données ne sont pas en RAM
Pour optimiser une requête SQL il est utile d'analyser son exécution avec EXPLAIN.
Modifier uniquement le schéma SQL ne me semble pas être une bonne idée, tout gain de performance qui serait obtenu par chance en utilisant un autre moteur serait perdu en temps de mise à jour de la base. S'il y a un réel besoin d'utiliser un autre moteur SQL alors il faudrait modifier tout legi.py pour qu'il devienne indépendant de SQLite.
En l’occurence, Pierre peut importer dans Drupal, pour son projet, une base MySQL (qui est courrament utilisée pour Drupal). Étant donné que c’est du SQLite, il faut soit convertir vers MySQL, soit trouver un connecteur SQLite. Je crois qu’il a cherché un peu SQLite sans trop trouver, puis la conversion vers MySQL semblait la plus facile, mais on s’est heurté au problème d’incompatibilité du schéma.
La solution de contournement temporaire a été de faire un dump puis d’appliquer les modifications de schéma, puis d’importer dans MySQL, et ça a marché. Bien sûr, il pourra continuer à faire ça à chaque import, mais si ça peut être facilité, c’est toujours ça de pris.
L’argument de performance me concerne plus particulièrement, j’aimerais bien que ça soit plus rapide, notamment pour faire de l’export sur une base régulière. Ça, c’est mon souhait, après les moyens d’y arriver sont ouverts. Je vais essayer d’importer dans MySQL pour vérifier, je vais peut-être effectivement me casser les dents. Et si ça ne marche pas, pourrais-t-on ajouter des clés primaires ? Je voyais qu’il n’y en avait pas sur sections.id ou articles.id. Enfin, ça c’est une autre pull request à discuter peut-être ailleurs.
sections.id et articles.id sont des clés primaires, elles ont unique not null (ce qui est à peu près la même chose que primary key).
À vrai dire je n'aime pas beaucoup l'idée de dégrader le schéma SQL pour se conformer aux limitations de MySQL.
Je pense que c'est l'inverse. Dans le cas présent, SQLLite ignore surement complètement l'index posé sur des champs de type "text".
En l'occurrence, changer le schéma tel que décrit dans le premier patch permettrait d'avoir des index sur les champs en question (ce qui était à priori dans le schéma original mais ignoré par SQLLite), ce qui boostera les performances.
Donc ça ne dégrade pas le schéma SQL. Bien au contraire. Ca le rend plus compatible et plus performant.
Modifier uniquement le schéma SQL ne me semble pas être une bonne idée
Si le schéma SQL n'est pas valide (ce qui est à priori le cas, cf mon commentaire plus haut), alors je ne vois pas pourquoi ça n'est pas une bonne idée.
S'il y a un réel besoin d'utiliser un autre moteur SQL alors il faudrait modifier tout legi.py pour qu'il devienne indépendant de SQLite.
SQLLite est censé être un dropin pour MySQL en mode embarqué. Il y'a très probablement un driver MySQL avec une interface compatible avec tout ce qui existe déjà dans legi.py. Dans le meilleur des cas, ça doit revenir à changer une ligne de code pour utiliser le driver MySQL au lieu de SQLLite, et les deux pourraient même rester utilisables via une option.
Dans le cas présent, SQLLite ignore surement complètement l'index posé sur des champs de type "text".
Non, d'ailleurs tu peux voir que les index sont bien présents dans le diagramme du schéma https://github.com/Legilibre/legi.py/issues/9#issuecomment-284219073. Un index sur une colonne de type text est parfaitement normal, SQLite et PostgreSQL les gèrent très bien, il n'y a que MySQL qui ne sait pas le faire.
SQLLite est censé être un dropin pour MySQL en mode embarqué.
Non, ce sont deux projets indépendants et incompatibles entre eux.
SQLite est super dans l'optique d'une utilisation personnel sur un client Desktop, pas de serveur de BD à installer.
MySQL ouvre vers un autre type d'utilisation, avec une intégration aisée avec des frameworks/CMS/sites utilisant déjà un serveur de BD.
Je pense que les deux utilisations sont intéressantes, et qu'une ORM permettant de mettre la BD que l'on veut derrière, avec choix par défaut SQLite, serait un choix logique.
Les ORM ont tendance à dégrader les performances et à empêcher l'optimisation. Pour rendre legi.py indépendant de SQLite je pencherais plutôt pour https://pypi.python.org/pypi/sql ou https://pypi.python.org/pypi/records.
Je ne vois toujours pas pourquoi on mettrait pas un champ text en varchar vu que ça ne change rien pour SQLLite mais qu'au moins ça marche en MySQL. Personne n'y perd, ceux qui veulent utiliser MySQL y gagnent. Où est le soucis ?
Les ORM sont une couche intermédiaire, donc oui par nature elle dégradent les performances. Mais c'est une petite constante, les perf dépendent surtout de la complexité de la requếte. Si ce niveau de perfs compte, alors faut réécrire legi.py en C...
BTW records est basé sur l'ORM SQLAlchemy.
@promethe42 Le soucis est qu'il s'agit d'une bidouille. On ne peut pas garantir que limiter artificiellement titrefull_s à 512 caractères fonctionnera toujours.
@fgallaire Indirectement legi.py est déjà majoritairement en C, à travers les modules qu'il utilise (libarchive, lxml, sqlite, etc). Le code python ne fait que le lien entre tout ça.
Tu as raison quand tu dis que la complexité des requêtes SQL est un facteur important, et c'est justement un point faible des ORMs : ils cachent les requêtes et rendent plus difficile l'optimisation de celles-ci.
(Je sais que records est basé sur SQLAlchemy, mais je doute qu'il utilise la partie ORM de celui-ci.)
Le soucis est qu'il s'agit d'une bidouille. On ne peut pas garantir que limiter artificiellement titrefull_s à 512 caractères fonctionnera toujours.
Inversement, un index sur un truc qui fait plus de 512 caractères me semble étrange.
Quelle est la longueur max aujourd'hui ? D'après ce que j'ai compris, c'est très (très) inférieur à 512 caractères. Alors que le besoin d'une compatibilité MySQL existe bel est bien aujourd'hui.
Ajouter un flag ou une option du genre schema=sqlite par défaut et schema=mysql pour ceux qui en ont besoin pourrait arranger tout le monde non ?
En solution alternative, on pourrait peut-être crowdsourcer sur github des scripts de migration vers d'autres formats ? (ex: postgres, json...)
Hello
Pour info j'ai fait un test avec postgresql; en convertissant le fichier sqlite vers postgres :
pgloader --cast "type day to varchar" legi.sqlite postgresql://postgres:[email protected]:5433/legi
je passe de 150s à 50s pour générer une version du code de la PI (avec archeo-lex)