- Accueil
- TUTORIELS
- LES B-ARBRES
- B+ arbres, bases de données et systèmes de fichiers
CHAPITRE 8 : B+ ARBRES, BASES DE DONNÉES ET SYSTÈMES DE FICHIERS
Presque aucune base de données n'utilise le B-arbre tel
qu'on vient de l'étudier. Toutes emploient une variante : le B+
arbre : qui corrige deux défauts précis. Les comprendre, c'est
comprendre pourquoi un CREATE INDEX accélère certaines requêtes et
pas d'autres.
Les deux défauts du B-arbre classique
Premier défaut : les parcours d'intervalle sont pénibles.
Pour lister toutes les clés entre deux bornes, il faut remonter chez le père
puis redescendre à chaque changement de feuille. Sur une requête du type
WHERE date BETWEEN … AND …, c'est désastreux.
Second défaut : les nœuds internes portent des données. Chaque clé d'un nœud interne traîne son enregistrement, ce qui réduit le nombre de clés par page, ce qui augmente la hauteur.
Les deux idées du B+ arbre
1. Toutes les données descendent dans les feuilles. Les nœuds internes ne contiennent que des clés servant d'aiguillage, sans aucune donnée associée. Une clé peut d'ailleurs apparaître à la fois comme séparateur en haut et comme donnée en bas.
2. Les feuilles sont chaînées entre elles. Chaque feuille pointe vers la suivante, formant une liste triée qu'on parcourt sans jamais remonter.
Ce que cela change
| B-arbre | B+ arbre | |
|---|---|---|
| Données | dans tous les nœuds | dans les feuilles seulement |
| Recherche d'une clé | peut s'arrêter en chemin | descend toujours jusqu'à une feuille |
| Parcours d'intervalle | remontées et redescentes | un simple parcours de liste |
| Clés par nœud interne | moins | beaucoup plus |
| Hauteur | plus grande | plus petite |
La recherche d'une clé isolée est légèrement moins bonne, puisqu'on ne peut plus s'arrêter dans un nœud interne. En échange, l'arbre est plus plat et les parcours deviennent triviaux. Pour une base de données, le marché est excellent.
Un B+ arbre, c'est un index au-dessus d'une liste triée.
Lire un plan de requête
Cette structure explique directement le comportement des bases de données.
-- rapide : descente dans l'index, 3 a 4 acces disque
SELECT * FROM clients WHERE id = 4218;
-- rapide : une descente, puis un parcours de la liste chainee
SELECT * FROM commandes WHERE date BETWEEN '2026-01-01' AND '2026-03-31';
-- rapide : l'index est deja trie, aucun tri a faire
SELECT * FROM clients ORDER BY nom LIMIT 20;
-- LENT : l'index est trie sur nom, pas sur ce qui suit le %
SELECT * FROM clients WHERE nom LIKE '%dupont';
La dernière requête est le cas d'école. Un index trié sur nom
permet de trouver tout ce qui commence par une chaîne, puisque c'est un
intervalle. Mais tout ce qui finit par une chaîne ne forme aucun
intervalle : l'index ne sert à rien, et la base parcourt toute la table.
La règle du préfixe. Un index B+ accélère les conditions
qui se traduisent par un intervalle sur l'ordre des clés : égalité,
comparaison, BETWEEN, LIKE 'debut%', et
ORDER BY sur la colonne indexée. Il ne sert à rien dès qu'on
applique une fonction à la colonne (WHERE UPPER(nom) = …) ou qu'on
cherche un suffixe.
Index composés
Un index peut porter sur plusieurs colonnes à la fois : les clés sont alors comparées dans l'ordre lexicographique.
CREATE INDEX idx ON commandes (client_id, date);
-- utilise l'index pleinement
WHERE client_id = 42 AND date > '2026-01-01'
-- utilise l'index partiellement (seulement client_id)
WHERE client_id = 42
-- n'utilise PAS l'index : la premiere colonne manque
WHERE date > '2026-01-01'
La raison est géométrique : les clés sont triées d'abord par
client_id, puis par date. Sans contrainte sur la
première colonne, les lignes cherchées sont éparpillées dans tout l'index.
C'est exactement comme chercher tous les mots dont la deuxième lettre
est un K dans un dictionnaire.
Où l'on en trouve
| Domaine | Exemples |
|---|---|
| Bases relationnelles | PostgreSQL, MySQL (InnoDB), Oracle, SQL Server, SQLite |
| Systèmes de fichiers | NTFS (1993), ext4 (2006), APFS (2017), Btrfs, XFS, HFS+ |
| Bases clé-valeur | Berkeley DB, LMDB |
Un système de fichiers fait le même travail qu'un index : retrouver un fichier par son nom dans un répertoire qui en contient des centaines de milliers, avec le moins d'accès disque possible. Le problème est identique, la solution aussi.
Et les autres structures ?
| Structure | Recherche | Intervalle | Bon pour |
|---|---|---|---|
| Table de hachage | O(1) | impossible | égalité seule, en mémoire |
| ABR équilibré (AVL, rouge-noir) | O(log₂ n) | correct | données en mémoire |
| B+ arbre | O(logt n) | excellent | données sur disque |
| LSM-tree | O(log n) × | correct | écritures massives |
La table de hachage bat le B+ arbre sur la recherche d'égalité pure, c'est
du O(1). Mais elle ne sait faire aucun parcours trié, aucun intervalle, aucun
ORDER BY. Pour un index de base de données, cela la disqualifie
dans la plupart des usages.
Les LSM-trees, eux, sont le concurrent sérieux du moment (LevelDB, RocksDB, Cassandra) : ils écrivent séquentiellement plutôt que de modifier des pages en place, ce qui convient mieux aux SSD et aux charges d'écriture intensives. Ils lisent en revanche moins bien.
À retenir
- Un B+ arbre ne garde les données que dans les feuilles, et les chaîne entre elles.
- Nœuds internes plus légers donc arbre plus plat ; parcours d'intervalle immédiat.
- Un index accélère ce qui se traduit par un intervalle : égalité, comparaison, préfixe, tri.
- Index composé : la première colonne commande, sans elle l'index est inutilisable.
- Tous les systèmes de fichiers et toutes les bases relationnelles sérieuses en utilisent.
Exercices d'application
(a) WHERE pays = 'Cameroun'
(b) WHERE pays = 'Cameroun' AND ville = 'Douala'
(c) WHERE ville = 'Douala'
(d) WHERE pays LIKE 'Cam%'
(e) ORDER BY pays, ville
Voir le corrigeMasquer le corrige
(a) Oui, partiellement. Les clés sont triées d'abord par pays : toutes les lignes du Cameroun forment un intervalle contigu. L'index les trouve directement.
(b) Oui, pleinement. Les deux colonnes sont contraintes dans l'ordre de l'index : la descente mène exactement aux lignes voulues.
(c) Non. Sans contrainte sur pays, les lignes de Douala sont dispersées dans tout l'index : une fois par pays ayant une ville de ce nom. Elles ne forment aucun intervalle. La base fera un parcours complet.
(d) Oui. LIKE 'Cam%' est une recherche par préfixe, donc un intervalle : tout ce qui est compris entre « Cam » et « Can ».
(e) Oui. L'index est déjà stocké dans cet ordre exact : la base le parcourt séquentiellement et n'a aucun tri à effectuer. C'est souvent le gain le plus spectaculaire d'un index.
Voir le corrigeMasquer le corrige
Parce que le O(1) ne porte que sur l'égalité, et qu'une base de données fait bien d'autres choses.
Une table de hachage disperse volontairement les clés : deux clés voisines atterrissent à des endroits sans rapport. Elle perd donc tout l'ordre, et avec lui :
- les intervalles (
BETWEEN,>,<) ; - le tri (
ORDER BYsans tri supplémentaire) ; - les recherches par préfixe ;
- le minimum et le maximum.
S'y ajoute un défaut propre au disque : le redimensionnement. Quand la table se remplit, il faut la reconstruire entièrement et réécrire tout l'index : inenvisageable sur plusieurs gigaoctets en production.
C'est pourquoi PostgreSQL propose bien des index HASH, mais que le type par défaut est BTREE. On réserve le hachage aux colonnes qu'on n'interroge qu'en égalité stricte.
Voir le corrigeMasquer le corrige
Descente. La hauteur vaut au plus :
log_200(10^8 / 2) = log(5x10^7) / log(200)
= 7,70 / 2,30
= 3,35 -> 4 niveauxLa racine étant en mémoire, cela fait 3 accès.
Parcours. Une feuille contient entre t − 1 = 199 et 2t − 1 = 399 clés ; comptons un remplissage réaliste d'environ 270. Pour 1 000 lignes :
1000 / 270 = 3,7 -> 4 feuillesLes feuilles étant chaînées, chacune coûte un seul accès : 4 accès.
3 + 4 = 7 accès disque pour 1 000 lignes
Soit 0,007 accès par ligne. À titre de comparaison, un parcours complet de la table lirait des centaines de milliers de pages. Et si l'index contenait aussi les colonnes demandées : un index couvrant : on éviterait même les 1 000 accès aux lignes elles-mêmes.
Cherchez avant d'ouvrir le corrige : c'est en butant sur les difficultes que l'on progresse.
Questions / Réponses
Ajouter un commentaire