Journal web moderne, bases de données et beauté logiciel libre

47
11
juin
2014

Sommaire

J'aimerais parler ici de mon expérience lors du développement de sql.js, un port de SQLite en javascript. Pour ceux qui ne s’intéressent pas aux technologies du web, la fin de ce journal pourrait quand même vous intéresser, on va parler de SQLite.

Web moderne

Ceux d'entre vous qui s'intéressent aux technologies modernes du web ont certainement entendu parler d’emscripten, et d’asm.js.

Emscripten est un compilateur de bitcode LLVM en Javascript. Il permet de compiler du code C ou C++ en javascript, très simplement. Le code javascript généré n’est bien sûr pas aussi rapide que le code natif équivalent, mais les performances sont assez bonnes. Sur Firefox, avec asm.js, le code tourne à peu près deux fois plus lentement que la version native. Le principal inconvénient que je trouve à emscripten est qu'il faut, pour l'utiliser sous linux, télécharger et compiler sa propre version de LLVM et de clang, ce qui est looong et pas pratique à mettre à jour.

asm.js, quant à lui, est un sous-ensemble de javascript conçu pour être facile à optimiser, et ainsi pouvoir s'exécuter rapidement. La syntaxe est dégueulasse, mais c'est pas grave, emscripten génère du code asm.js pour nous.

SQLite

Vous connaissez certainement déjà SQLite3, le moteur de bases de données le plus utilisé au monde. Si vous vous y êtes déjà un peu intéressant, vous connaissez certainement ses caractéristiques, qui le rendent unique:
* Une base de donnée est stockée dans un seul fichier
* Le binaire SQLite est minuscule (moins d'un Mo), et la bibliothèque sqlite peut être liée statiquement dans votre programme.
* Le code a été placé dans le domaine public

Par contre, vous ne connaissez peut-être pas SQLite4, une évolution de SQLite3 (par les mêmes développeurs), qui n’a pas encore de version stable (et que j’ai aussi porté en javascript). Cette version apporte de biens meilleures performances, et surtout, elle utilise un système de base de données de type clef-valeur, que l'on peut changer à la volée.
Et ça, c’est génial! Cela signifie que l'on pourra bientôt profiter de tous les avantages de SQLite même pour de grosses bases de données. Il suffira d’utiliser un système de base de données clef-valeur qui supporte les grands ensembles de données, comme LevelDB.

Quand on mélange les deux…

sql.js, avant

sql.js, un port de sqlite en javascript, était au départ un projet de kripken, le créateur et principal mainteneur d’emscripten, qui date de début 2012. Le port fonctionnait, mais question fonctionnalités, on restait un peu sur sa faim: une seule méthode db.exec, qui exécutait du SQL et retournait les résultats dans un format pas pratique. Les données étaient toujours converties en chaînes de caractères avant d’être retournées. Le projet n’avait aucun test unitaire, le dernier commit date d’il y a plus d’un an, et l’auteur ne répond plus sur le bugtracker…

Pourtant, le projet semble avoir des utilisateurs. 104 forks et 883 stars sur github, et plusieurs téléchargements par jour sur npm à l’heure où j’écris ces lignes.

sql.js, maintenant

Je suis étudiant, et lors d’un TD, j’ai eu besoin de pouvoir tester des commandes en SQL, sur un ordi avec rien du tout d’installé. Je ne connaissais pas encore SQLfiddle, mais j’avais déjà entendu parler de sql.js, donc j’ai utilisé sa démonstration en ligne.

Le soir, en rentrant chez moi, très agaçé des petits défauts de la démonstration que j'avais utilisée, j'ai forké le projet, et commencé à travailler sur une meilleure interface graphique. Quand j'ai été content de moi, j’ai fait une pull request. Comme l’auteur tardait à répondre, j’ai commencé à bidouiller le reste du code. Et de fil en aiguilles, j'ai fini par réécrire tout le code, à changer l’API pour avoir quelque chose de facile à utiliser, à ajouter des tests, de la documentation… Et je suis assez fier de l’état du projet aujourd’hui.

Il est utilisable sans modifications à la fois depuis node.js, dans le navigateur, et en tant que web worker. Il est disponible sur npm, et s’utilise avec un simple

var sql = require('sql.js');
var db = new sql.Database();

Il retourne les données dans leur format original, y-compris les BLOBs, retournés sous forme de tableau d’octets.

var res = db.exec("SELECT * FROM table1; SELECT * FROM table2");
// Ce qui peut retourner:
[
    {columns:['a','b'], values:[[0,'hello'],[1,'world']]}, //Le contenu de table1
    {columns:['c','d'], values:[[null,[1,2,3]],[42,'blabla'],[666,666]]} //Celui de table2
    // Et oui, la colonne d contient des données de types différents. C’est possible grâce à SQLite. C’est impossible avec presque tous les autres SGBD
]

Et il permet d'utiliser des requêtes préparées (prepared statements), auxquelles on associe les paramètres que l'on veut, sans risquer de vilaines injections sql:

db.run("INSERT INTO table1 VALUES (?,?)", [3,[121,111,117,99,114,97,99,107,101,100,105,116]]);

Mais aussi:

var stmt = db.prepare("SELECT * FROM table1 WHERE a=$aval AND b=$bval");
var result = stmt.getAsObject({$aval : 1, $bval : 'world'});
// result contient maintenant:
{a:1, b:'world'}

Conclusion

Aujourd’hui, on fait tout ce qu’on veut sur le web, et bientôt, ce sera encore mieux. Les trucs funs qui sont pour bientôt: ECMASCRIPT 6, aka Harmony, emscripten SDK pour linux, sqlite4.js

Liens

  • Page GitHub du Projet : Je vous encourage bien sûr à venir lire mon code, le tester, ouvrir les tickets…
  • la demo : Elle permet d’exécuter du SQL, mais aussi de lire, modifier, puis sauvegarder des bases SQLite3 directement depuis votre navigateur.
  • emscripten, sans qui je ne serai rien
  • sqlite, le SGBD le plus cool qui soit
  • # promotion en dépêche ?

    Posté par  (site web personnel) . Évalué à 9.

    Je propose, une idée comme ça.

    ウィズコロナ

    • [^] # Re: promotion en dépêche ?

      Posté par  (site web personnel) . Évalué à 6.

      J'y ai pensé au moment de l'écrire, mais comme je raconte un peu ma vie, j'ai finalement décidé de proposer un journal.

      Mais comme tu le proposes, je vais poster ce contenu en tant que dépêche aussi…

  • # BDD dans le cloud

    Posté par  . Évalué à 6.

    Si je comprends bien, vu que c'est du JS, la base SQLite est alors un fichier créé en local dans le cache du navigateur, c'est bien ça ?

    • [^] # Re: BDD dans le cloud

      Posté par  (site web personnel) . Évalué à 5.

      En fait, la base de données est stockée intégralement en mémoire. L'avantage, c'est que c'est rapide (du moins, pas trop lent).

      L'inconvénient, c'est qu'on se limite à de petites bases de données.

      C'est aussi pour ça que j'attends beaucoup de sqlite4. Il permettra de faire assez simplement le lien entre SQLite et les mécanismes qui permettent de stocker des données sur le disque en JavaScript, comme localStorage.

      • [^] # Re: BDD dans le cloud

        Posté par  (site web personnel, Mastodon) . Évalué à 10.

        C'est aussi pour ça que j'attends beaucoup de sqlite4. Il permettra de faire assez simplement le lien entre SQLite et les mécanismes qui permettent de stocker des données sur le disque en JavaScript, comme localStorage.

        Oui, donc en utilisant IndexedDb ou localStorage comme backend. Et le saviez-tu ? L'implementation de localStorage et IndexedDb dans les navigateurs (en tout cas dans Firefox), repose sur… SQLite (natif).

        En résumé : une implémentation de SQLite4 en javascript qui utilise IndexedDb qui utilise SQLite.

        Bref, pour les pages web : strictement aucun intérêt. Autant utiliser directement IndexedDb. Sauf à proposer un interpréteur SQL par dessus IndexedDb. Mais je doute que porter SQLite4 reste d'un grand intérêt : il n'y a pas besoin de tout le code de SQLite4 (converti donc en asm.js) pour avoir au final qu'un interpreteur SQL.

        Bientôt, on va voir arriver une implémentation de Redis JS qui repose sur l'implémentation JS de sqlite4 qui repose sur IndexedDb qui repose sur un sqlite natif…

        • [^] # Re: BDD dans le cloud

          Posté par  (site web personnel) . Évalué à 1.

          il n'y a pas besoin de tout le code de SQLite4 (converti donc en asm.js) pour avoir au final qu'un interpreteur SQL.

          Quelle partie de SQLite serait inutile? Toute la partie concernant le stockage de données serait implémentée en js avec un binding vers localStorage. Le code compilé contiendrait toute la logique de la base de données relationnelle, et ça, c'est utile. Et pour les performances, je pense qu’on a de la marge.

        • [^] # Re: BDD dans le cloud

          Posté par  . Évalué à 6.

          Bientôt, on va voir arriver une implémentation de Redis JS qui repose sur l'implémentation JS de sqlite4 qui repose sur IndexedDb qui repose sur un sqlite natif…

          Zut ! J'étais en train d'écrire un journal…

        • [^] # Re: BDD dans le cloud

          Posté par  . Évalué à 3.

          Sauf à proposer un interpréteur SQL par dessus IndexedDb.

          SQLite4 est un interpréteur SQL utilisant un moteur de stockage k,v.

          Donc ça a bien un intérêt.

    • [^] # Re: BDD dans le cloud

      Posté par  . Évalué à 4.

      Je dirai même plus quels sont les cas d'usages possibles ? J'ai du mal à imprimer sur ce coup.

      • [^] # Re: BDD dans le cloud

        Posté par  (site web personnel) . Évalué à 2.

        J’ai envie de dire: C'est vous qui voyez!

        Ça peut être utile pour des applications qui traitent des bases de données de quelques milliers d’enregistrements, et qui peuvent faire des requêtes diverses sur les données. Par exemple: afficher des graphes. Cela permet de soulager le serveur, et de gagner en performances (plus besoin d’une requête réseau par requête à la BDD).

        Bien sûr, le fait que la base de données doive-t-être téléchargée entièrement côté client exige qu’elle ne contienne pas de données sensibles. Le fait qu’elle soit stockée intégralement en mémoire exige qu’elle ne soit pas trop grosse.

        J’ai eu quelques retours d’utilisateurs, apparemment la plupart cherchent à faire des systèmes de visualisation de données: leurs données sont déjà dans des bases SQLite, et ils veulent utiliser des bibliothèques javascript comme d3 pour les visualiser.

        • [^] # Re: BDD dans le cloud

          Posté par  . Évalué à 4.

          Une base sql pour visualiser quelques milliers de point c'est pas un poil beaucoup super overkill ?

          • [^] # Re: BDD dans le cloud

            Posté par  . Évalué à 2.

            Ben j'avoues que si tout doit etre traite cote serveur pour stripper ce qui est sensible, que c'est en memoire (et donc read only), non acid, pas thread safe, tres peu de contraintes et avec un typage primitif (sqlite oblige) je me demande un peu quel est le but.

            A ce compte la, vaut pas mieux juste retourner du bson (ou juste du json gzipé, quitte a faire le goret sur le ram, autant pas s'emmerder), et avoir un moteur de predicat decent, a appliquer directment sur le graph d'objet?

            Linuxfr, le portail francais du logiciel libre et du neo nazisme.

            • [^] # Re: BDD dans le cloud

              Posté par  (site web personnel) . Évalué à 2.

              C'est en mémoire, mais pas read only. Tu peux exporter ta base après coup.
              C'est ACID, parce que SQLite respecte les propriétés acid. C'est thread safe, pour la simple raison que le seul moyen de faire des threads en js dans le navigateur, ce sont les web workers, et qu'ils ne permettent pas de partager la mémoire.

              Si la base est déjà en SQLite côté serveur, et qu'elle ne contient pas de données sensibles, ça peut valoir le coup de l'envoyer direct vers le client.

          • [^] # Re: BDD dans le cloud

            Posté par  . Évalué à 2.

            Un exemple que je vois tout les jours. C'est le téléchargement d'un rrd ( qui font environ 24Mo chacun ) par un .js qui permet de naviguer et de zoomer directement dedans. C'est pas mal pratique mais très lourd même en téléchargeant le rrd à ~6Mo/s.

            Dans le cas d'un SQLite, on peut penser ne téléchargé que ce qui est nécessaire. Premier affichage, on envoie que les données de la période par défaut. Si l'utilisateur commence à naviguer dedans, on télécharge à la demande puis on télécharge en tâche de fond une période un peu plus grande.

            • [^] # Re: BDD dans le cloud

              Posté par  . Évalué à 4.

              C'est quoi l'interet de faire une conversion rrd -> base sqlite, puis d'utiliser une version jsifier de sqlite pour afficher ton graphe par rapport à… juste exporter les données dont tu as besoin ?

              Tu mets une énorme brique au milieu pour 3 pauvres fonctionalités. Tout le côté ACID on s'en balance t'es dans un environnement mono-threadé où tu n'auras jamais aucun problème de concurrence ou de visibilité. Tu te balances de la persistance dans 90% des usages. Tu travailles sur un petit set de donnés qui est très facilement traitable à la main.

              Bref j'ai un peu l'impression qu'on transcode et utilise un "gros monstre" pour… pas grand chose.

              • [^] # Re: BDD dans le cloud

                Posté par  . Évalué à 3.

                Tu te balances de la persistance dans 90% des usages.

                Et pour ça tu peut utiliser localstorage. Tu peux aussi t'en servir pour avoir un cache local et réduire la quantité de données à télécharger.

                Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

  • # Comme en terre

    Posté par  . Évalué à 3.

    // Et oui, la colonne d contient des données de types différents. C’est possible grâce à SQLite. C’est impossible avec presque tous les autres SGBD

    C'est pas ça l'intérêt d'avoir une base de données ?

    • [^] # Re: Comme en terre

      Posté par  . Évalué à 4.

      Tu confond ligne et colonne.

      Par contre pour moi c'est un gros défaut de sqlite…

      Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

      • [^] # Re: Comme en terre

        Posté par  . Évalué à 1.

        Tu confond ligne et colonne.

        Si on compare des choux avec des carottes, alors on compare les cagettes de choux avec les cagettes de carottes (la cagette étant covariante bien sûr). Après rien n'interdit de définir des palettes de cagettes de ce qu'on veut, j'imagine.

    • [^] # Re: Comme en terre

      Posté par  (site web personnel) . Évalué à 1.

      Le système de types de sqlite est tout de même un peu plus fin que juste "démerdez-vous" : http://www.sqlite.org/datatype3.html

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.