Menu

SQLite en mémoire : la base jetable avec :memory:

Comment fonctionne la base SQLite en mémoire, quand dégainer :memory:, et ce qui la distingue d'une base stockée dans un fichier classique.

Cette page contient des éditeurs exécutables — modifiez, exécutez et voyez la sortie instantanément.

Une base de données qui vit en RAM

SQLite reconnaît un nom de fichier un peu particulier : :memory:. Ouvrez une base avec ce nom et SQLite zappe complètement le disque — toute la base réside en mémoire vive. Les tables, les index, les transactions, les clés étrangères, absolument toutes les fonctionnalités marchent à l'identique. La seule différence ? Dès que la connexion se ferme, la base part en fumée.

Depuis la ligne de commande :

sqlite3 :memory:

Vous voilà à l'invite SQLite avec une base vide toute neuve, qui n'existe qu'en mémoire. Créez une table, insérez quelques lignes, lancez une requête — bref, comme d'habitude :

Quittez la session et les données s'évaporent. Aucun fichier ne reste sur le disque, pour la bonne raison qu'aucun fichier n'a jamais été créé.

À quoi ça sert, une base SQLite en mémoire ?

Une base de données qui ne survit pas à un redémarrage, ça ressemble plus à un bug qu'à une fonctionnalité. Pourtant, c'est franchement utile dans trois cas de figure.

Les tests. Chaque test démarre avec une base propre en quelques millisecondes. Pas de fichier temporaire à nettoyer, pas de résidus du run précédent, pas de fixture partagée qui se retrouve verrouillée. La plupart des suites de tests Python, Node ou Go qui s'appuient sur SQLite ouvrent :memory: précisément pour cette raison.

L'analyse jetable. On charge un CSV, on lance quelques requêtes, on jette le tout. C'est plus rapide que de monter une vraie base, et plus simple que de parser le fichier à la main dans le code à chaque fois.

Cache et espace de travail temporaire. Au sein d'un programme qui tourne longtemps, une base SQLite en mémoire fait un moteur de requêtes ad hoc étonnamment efficace pour des données déjà chargées en RAM.

Le fil rouge : on veut du SQL, mais pas de persistance.

Performances : plus rapide, mais pas miraculeux

Une base en mémoire évite le disque : les écritures qui passeraient normalement par le système de fichiers deviennent de simples mises à jour en RAM. Les charges de travail limitées par les I/O y gagnent nettement. Celles qui sont limitées par le CPU — planification de requêtes complexes, gros tris — ne bougent quasiment pas, puisque SQLite gardait déjà les pages chaudes en mémoire de toute façon.

Petite démonstration pour montrer à quel point la syntaxe est identique :

Cette requête tournait sur une base en mémoire, mais c'est exactement le même SQL qu'avec un fichier. Le moteur, lui, s'en fiche complètement.

SQLite en mémoire ou sur fichier : lequel choisir ?

Le compromis est simple, et autant le poser noir sur blanc :

  • Base sur fichier (mydata.db) : survit aux redémarrages. Plusieurs processus peuvent l'ouvrir en même temps. Elle résiste aux crashs (en mode WAL, en grande partie). À utiliser dès que vos données doivent être conservées.
  • Base en mémoire (:memory:) : disparaît à la fermeture. Privée à la connexion qui l'a ouverte (par défaut). Plus rapide pour les traitements jetables avec beaucoup d'écritures. Idéale pour les tests, les bouts de code temporaires et les caches éphémères.

Dans le doute, prenez un fichier. La base en mémoire, c'est le cas particulier.

Chaque connexion a sa propre base

Un piège classique : ouvrir :memory: deux fois vous donne deux bases totalement distinctes. Elles ne partagent ni tables, ni données, et ne se voient pas l'une l'autre.

-- Terminal 1
sqlite3 :memory:
sqlite> CREATE TABLE t (x); INSERT INTO t VALUES (1);

-- Terminal 2
sqlite3 :memory:
sqlite> SELECT * FROM t;
Error: no such table: t

Ce n'est pas un bug — c'est voulu. :memory: signifie « une base privée, propre à cette connexion ». Le principe vaut aussi à l'intérieur d'un même programme : si votre code ouvre deux connexions vers :memory:, chacune obtient sa propre base, totalement isolée de l'autre.

Partager une base SQLite en mémoire entre plusieurs connexions

Si vous avez vraiment besoin que plusieurs connexions accèdent à la même base SQLite en mémoire, c'est possible grâce aux noms de fichiers au format URI combinés au cache partagé. La chaîne magique, c'est file::memory:?cache=shared :

sqlite3 'file::memory:?cache=shared'

Toute connexion ouverte dans le même processus avec exactement cette URI rejoint la même base. Dès que vous les fermez toutes, la base disparaît.

Vous pouvez aussi nommer votre base en mémoire, ce qui est pratique lorsque vous souhaitez gérer plusieurs bases partagées distinctes :

sqlite3 'file:mydb?mode=memory&cache=shared'

Ici, le nom mydb n'est qu'une étiquette — il n'y a toujours aucun fichier sur le disque. Deux connexions qui ouvrent file:mydb?mode=memory&cache=shared partagent la même base ; en revanche, une connexion qui ouvre file:other?mode=memory&cache=shared se retrouve avec une base différente.

Sauvegarder une base SQLite en mémoire sur le disque

Il arrive qu'on enchaîne tout un traitement en mémoire et qu'on souhaite finalement conserver le résultat. La CLI propose justement la commande .backup pour ça :

sqlite3 :memory:
sqlite> CREATE TABLE results (id INTEGER, score REAL);
sqlite> INSERT INTO results VALUES (1, 0.91), (2, 0.87);
sqlite> .backup snapshot.db
sqlite> .quit

snapshot.db est maintenant une base sur disque tout ce qu'il y a de plus classique, avec exactement le même contenu. Vous pourrez la rouvrir plus tard avec sqlite3 snapshot.db et reprendre là où vous en étiez.

L'inverse fonctionne aussi : .restore charge une base fichier dans la mémoire de la connexion en cours :

sqlite3 :memory:
sqlite> .restore snapshot.db
sqlite> SELECT * FROM results;

Du côté du code applicatif, l'API C de SQLite expose les mêmes mécanismes via sqlite3_backup_init, et la plupart des bindings de langage l'enveloppent. Le module sqlite3 de Python, par exemple, propose Connection.backup().

Un piège classique

On voit parfois des gens essayer de « sauvegarder » une base SQLite en mémoire en attachant un fichier puis en recopiant les données :

Cette approche fonctionne pour de simples copies de tables, mais elle ne reproduit pas fidèlement les index, les triggers, les vues ou les clés étrangères. Pour obtenir une copie exacte d'une base entière, utilisez .backup (ou l'API de backup) — la copie se fait au niveau des pages, octet par octet.

Ce qu'il faut retenir

  • :memory: est un nom de fichier spécial dans SQLite qui crée une base en mémoire vive, sans fichier sur le disque.
  • Le SQL reste identique à celui d'une base sur fichier — mêmes tables, mêmes requêtes, mêmes contraintes.
  • Chaque connexion à :memory: est isolée ; passez par une URI avec cache partagé (file::memory:?cache=shared) quand plusieurs connexions doivent accéder à la même base.
  • C'est l'outil idéal pour les tests, l'analyse jetable et les caches éphémères — pas pour des données qui doivent survivre à un redémarrage.
  • Quand vous décidez de garder le contenu, faites passer la base mémoire sur disque avec .backup.

La suite : créer des tables

Vous avez déjà aperçu CREATE TABLE au passage dans plusieurs exemples. La page suivante prend le temps de tout détailler : la définition des colonnes, les types, les contraintes que l'on peut y rattacher, et les petits choix qui rendent un schéma agréable à utiliser au quotidien.

Questions fréquentes

Comment créer une base SQLite en mémoire ?

Il suffit d'ouvrir SQLite avec le nom de fichier spécial :memory: à la place d'un chemin. En ligne de commande, ça donne sqlite3 :memory: ; depuis une bibliothèque, vous passez :memory: comme nom de fichier dans l'appel connect. La base vit en RAM et disparaît dès que la connexion se ferme.

C'est quoi :memory: dans SQLite ?

:memory: est un nom de fichier magique que SQLite interprète comme : « pas de fichier, tout reste en RAM ». Vous obtenez une base SQLite complète — tables, index, transactions, tout y est — mais rien n'est jamais écrit sur disque. Et chaque connexion qui ouvre :memory: se retrouve avec sa propre base privée.

Deux connexions peuvent-elles partager une base SQLite en mémoire ?

Pas par défaut : chaque connexion :memory: est isolée des autres. Pour en partager une, ouvrez-la avec une URI du type file::memory:?cache=shared et activez le cache partagé. Toutes les connexions qui ouvrent cette même URI dans le même processus verront alors la même base.

Peut-on sauvegarder une base SQLite en mémoire sur disque ?

Oui, sans problème. Utilisez la commande .backup du CLI ou l'API de backup de votre bibliothèque pour copier la base en mémoire vers un fichier. Autre option : faire un ATTACH sur une base fichier puis un INSERT INTO fichier.table SELECT * FROM main.table pour transférer les données.

Coddy programming languages illustration

Apprendre à coder avec Coddy

COMMENCER