LMDB : la base NoSQL le plus rapide du monde

OpenLDAP-LMDB (Lightning Memory-Mapped Database) ou LMDB est une base de données embarquée transactionnelle de stockage clé-valeur qui est disponible sous Linux. En 2009, le projet OpenLDAP est préoccupé par l’avenir de Berkeley DB, passé dans le giron d’Oracle. Le projet OpenLDAP a finalement décidé de faire un fork de Berkeley DB, appelée MDB. Cette librairie devient LMDB et est utilisée massivement sous Linux.

Portage sous Windows

Avant de pouvoir l’utiliser sous forme de DLL Windows, il est impératif de migrer le code Linux vers Windows. La librairie contient du code pour Windows mais le portage reste incomplet car l’utilisation des noms de fichiers contient un / au lieu de \\ et cela ne marche que sous Linux, une fois cette modification effectuée, Il faut donc exporter les diverses fonctions pour obtenir une DLL.

LMDBWindowsDll

Le portage de la DLL sous Windows est disponible sur : https://github.com/ChristophePichaud/LMDBWindows/LMDBWindowsDll

En Debug, la DLL LMDBWindowsDllD64.dll fait 235 KB. En Release, elle en fait moins de 100 KB, ce qui est très léger.

Utilisation de LMDB API

L’API est du C pur et dur: il y a des structures à définir et des structures à utiliser. Les fonctions sont préfixées par mdb_, Bien que l’utilisation du C soit basic, elle peut rebuter certaines personnes. Il faut passer des buffers, des longueurs, autrement dit du C. Il est également préférable d’encapsuler l’API C en C++ et mettre à disposition des std::string.

Cette version d’API est beaucoup plus simple à utiliser: il faut déclarer un objet, faire appel à Init en y passant le nom de la base de données, et ensuite faire Get/Set comme on le souhaite.

Comme on le voit ci-dessus, l’ajout de données se fait par clé et valeur.

La base de données

Elle est constituée de deux fichiers :

  • data.mdb
  • lock.mdb

La méthode Init créé un répertoire du nom de la base dans c:\temp pour y stocker ces deux fichiers.

L’ouverture de la base

Comme vu précedemment, Init créé un répertoire, mais pas uniquement :

Init ouvre également une connexion à la base via mdb_dbi_open et positionne certains paramètres.

Gestion de la transaction

La transaction est créée via mdb_txn_begin et mdb_txn_commit :

Insertion de données

La création des données se fait via un appel à mdb_put :

Récupération de données

La récupération des données se fait via un appel à mdb_get ;

Evaluation des performances

Reprenons notre exemple et ajoutons des indicateurs de temps :

Le programme est simple. Il prend un nombre d’opérations à réaliser et ensuite il fait autant de GET et autant de SET sur un jeu de clé / valeur simple. Testons ce petit programme :

Opération Nombre Durée (ms)
get 1 0
set 1 0
get 10 0
set 10 0
get 100 15
set 100 0
get 1000 63
set 1000 15
get 10000 109
set 10000 63
get 100000 1141
set 100000 640

 

Modifions maintenant le programme pour insérer et récupérer des documents jSON :

Voici le résultat :

Opération Nombre Durée (ms)
get jSON 1 0
set jSON 1 0
get jSON 10 0
set jSON 10 0
get jSON 100 0
set jSON 100 0
get jSON 1000 16
set jSON 1000 16
get jSON 10000 218
set jSON 10000 63
get jSON 100000 2375
set jSON 100000 672

 

Les performances sont exceptionnelles et la taille de la base de données est conséquente (53 MB) :

Application pratique

Vous souhaitez utiliser une base de données de cache dans votre site web sur Azure mais vous hésitez entre DocumentDB ou MongoDB. Vous pouvez essayer LMDB, c’est une base gratuite et rapide. De plus LMDB possède aussi des fonctionnalités de curseur pour lire le contenu de la base.

Explorer la base

Voici le code qui permet de parcourir les données :

Le code de GetAllData() n’est pas compliqué, on déclare un curseur et on itère sur la méthode GetFromCursor. Voici le programme client :

CLMDBWrapperEx wr1;

wr1.Init(db);

wr1.GetAllData();

Voici la sortie console, on y remarque les documents jSON :

Si on modifie le programme client pour avoir des indications de temps :

Elasped Time for GetAllData: 32 ms

Il faut moins de 100ms pour charger 200.000 items soit 53 MB de data en RAM.

C’est du C/C++ ! C’est extrêmement performant.

Interop en C# .NET

Il existe des bindings pour le langage C#. C’est le rôle de LMDB.NET. Un portage C# qui fait des appels Interop à la DLL qui correspond. Voici le diagramme de classes simplifié :

Voici comment ouvrir une base :

Voici le code de récupération des informations jSON via le cursor :

Que vous souhaitiez utiliser SQLite ou un fichier de config, une base Azure comme Document DB ou MongoDB, il est important de prendre en compte cette nouvelle librairie qu’est LMDB. C’est gratuit, rapide et facile à mettre en œuvre. Elle explose les performances de toutes les bases NoSQL. Vous pouvez l’utiliser dans un container Docker avec la mise à disposition des données soit volatiles dans le container, soit persistentes dans des volumes partagés. LMDB et LMDB.NET, c’est le meilleur des deux mondes, le C++ pour la rapidité et le C# pour la facilité d’utilisation. Lancez-vous !

L’expertise Devoteam Modern Applications

Devoteam Modern Applications est spécialiste dans le développement et l’utilisation des technologies Microsoft .NET. 

Avec LMDB, nous sommes capable d’apporter a nos clients un cache NoSQL pour des applications ASP.NET MVC. Par exemple on peut leur permettre de stocker des milliers d’informations en provenance de la base de données SQL Server et de les servir a leur client rapidement. C’est aussi une vitrine technologique pour permettre la mise en œuvre des containers sur Azure.

LMDB permet de concurrencer des produits comme MongoDB, Document DB et Azure Cosmos DB… en terme de prix et de performances. DMA réalise aussi des migrations applications traditionnelles en Microsoft .NET, .NET Core et sous Azure.


Découvrir l’offre Agile IT

devoteam

Contact

Christophe Pichaud

Architecte Microsoft chez M Applications by Devoteam