Il est important de souligner que la base de données ne se résume pas simplement à une requête à optimiser, mais également à une structure de données qu'il convient de choisir et de configurer avec soin.
1. Une structure de données
sophistiquée et spéciale
Ben Khalfallah Héla
2.
3. La BD, au-delà d'un simple support de stockage
Clustered Index basé sur B-Tree
Implémentation interne basée sur LSM-Tree
4. « La structure des données décide essentiellement de la manière dont nous devons les
stocker et les récupérer. Vos applications traitent des données présentes dans une variété
de formats, le choix de la bonne base de données devrait inclure le choix des bonnes
structures de données pour le stockage et l'extraction des données. Si vous ne sélectionnez
pas les bonnes structures de données, votre application prendra plus de temps pour
récupérer les données de la base de données et nécessitera également plus d'efforts pour
résoudre les problèmes liés aux données. »
5.
6. Architecture of a database management system
https://sgbd.developpez.com/tutoriels/cours-complet-bases-de-
donnees/?page=objectifs-et-architecture-des-sgbd
11. “Two variants of b-trees are used by SQLite. "Table
b-trees" use a 64-bit signed integer key and store all
data in the leaves. "Index b-trees" use arbitrary keys
and store no data at all.”
“Each ordinary SQL table in the database schema is
represented on-disk by a table b-tree. Each entry in
the table b-tree corresponds to a row of the SQL
table.”
“Each SQL index, whether explicitly declared via a
CREATE INDEX statement or implied by a UNIQUE or
PRIMARY KEY constraint, corresponds to an index b-
tree in the database file. Each entry in the index b-
tree corresponds to a single row in the associated
SQL table”
https://www.sqlite.org/arch.html
https://sqlite.org/fileformat.html#b_tree_pages
12. “Oracle Database provides several indexing
schemes, which provide complementary
performance functionality. B-tree indexes
are the standard index type. They are
excellent for highly selective indexes (few
rows correspond to each index entry) and
primary key indexes. Used as concatenated
indexes, a B-tree index can retrieve data
sorted by the indexed columns.”
“Different types of indexes are useful in
different scenarios. For example, B-tree
indexes are often used in online
transaction processing (OLTP) systems with
many concurrent transactions, while
bitmap indexes are often used in data
warehousing systems that are mostly used
for queries.” https://docs.oracle.com/en/database/oracle/oracle-database/21/cncpt/indexes-and-
index-organized-tables.html#GUID-ACA0308E-5F01-4236-81D3-D0CDE5CB6695
13. [...] Magma, a write-optimized high data density key-value storage engine used in the Couchbase NoSQL
distributed document database. [...] Magma, a hybrid key-value storage engine that combines LSM Trees and a
segmented log approach from log-structured file systems.
https://dl.acm.org/doi/abs/10.14778/3554821.3554839
14. « With the exception of spatial indexes, InnoDB indexes are B-tree data structures. Spatial
indexes use R-trees, which are specialized data structures for indexing multi-dimensional data.
Index records are stored in the leaf pages of their B-tree or R-tree data structure. »
https://dev.mysql.com/doc/refman/8.3/en/innodb-physical-structure.html
15. « PostgreSQL B-Tree indexes are multi-level tree structures, where each level of the
tree can be used as a doubly-linked list of pages. »
23. def hauteur_arbre(m, n):
"""
Calcule la hauteur de l'arbre B en fonction du facteur de chargement maximum (m) et du nombre total de clés (n).
"""
return math.ceil(math.log(n + 1, m)) // H=logm(n+1)
def profondeur_arbre(h):
"""
Calcule la profondeur de l'arbre B en fonction de sa hauteur (h).
"""
return h – 1 // D=H−1
def nombre_maximal_cles(m):
"""
Calcule le nombre maximal de clés dans un nœud de l'arbre B en fonction du facteur de chargement maximum (m).
"""
return m – 1 // M=m−1
# Exemple d'utilisation :
facteur_chargement_max = 5
nombre_total_cles = 100
hauteur = hauteur_arbre(facteur_chargement_max, nombre_total_cles)
profondeur = profondeur_arbre(hauteur)
nombre_maximal_cles_noeud = nombre_maximal_cles(facteur_chargement_max)
print("Hauteur de l'arbre B:", hauteur)
print("Profondeur de l'arbre B:", profondeur)
print("Nombre maximal de clés dans un nœud:", nombre_maximal_cles_noeud)
25. Le facteur de chargement maximum détermine le nombre de clés qu'un nœud peut
contenir.
Un facteur plus élevé peut réduire la hauteur de l'arbre, améliorant les performances
de recherche, mais peut aussi entraîner une fragmentation (les données sont
stockées de manière non continue sur le disque, création de trous ou d'espaces non
utilisés entre les données) et des opérations de division plus fréquentes.
Son choix dépend de divers facteurs comme la taille des données et les performances
requises. Des valeurs par défaut sont généralement fournies, mais elles peuvent être
ajustées selon les besoins.
26. Dans MySQL ou MariaDB, le facteur de
chargement maximum est généralement
contrôlé par le paramètre innodb_fill_factor.
Ce paramètre spécifie le pourcentage
d'espace vide autorisé dans chaque page
d'index InnoDB avant qu'une division ne soit
déclenchée. Il est possible de le configurer
dans le fichier de configuration my.cnf ou en
utilisant la commande SET dans MySQL.
Dans Oracle Database, le facteur de
chargement maximum est influencé par le
paramètre PCTFREE lors de la création de
l'index. PCTFREE spécifie le pourcentage
d'espace libre à conserver dans chaque bloc
de données pour les mises à jour ultérieures.
On peut spécifier cette valeur lors de la
création de l'index à l'aide de la clause
PCTFREE.
Dans SQL Server, le facteur de chargement
maximum est influencé par le paramètre
FILLFACTOR lors de la création de l'index. On
peut spécifier cette valeur lors de la création
de l'index à l'aide de la clause WITH
(FILLFACTOR = value).
Pour PostgreSQL on peut utiliser la propriété
fillfactor lors de la création de la table pour
spécifier le pourcentage de remplissage
initial des pages de données.
30. L'index racine de la B-tree est généralement stocké dans une page spéciale qui est
facilement accessible.
Chaque page de la B-tree peut comporter des entêtes contenant des métadonnées sur la
page elle-même, telles que son numéro de page, son type, des informations sur la taille
des données, etc.
Chaque page (nœud) peut contenir un nombre fixe de clés et de pointeurs vers d'autres
pages ou vers les données elles-mêmes.
Les pages sont des unités de stockage de données de taille fixe, souvent de quelques kilo-
octets, utilisées par le système de gestion de base de données (SGBD) pour organiser et
manipuler les données sur le disque.
Chaque nœud de l'arbre est généralement sauvegardé dans une page distincte sur le
disque.
31. Disque dur
|
v
+----------------------------------------+
| Page 1 (Noeud 1) |
|----------------------------------------|
| Page 2 (Noeud 2) |
|----------------------------------------|
| Page 3 (Noeud 3) |
|----------------------------------------|
| Page 4 (Noeud 4) |
|----------------------------------------|
| Page 5 (Noeud 5) |
+----------------------------------------+
✓ Plutôt que d'écrire les pages de la B-tree de
manière aléatoire sur le disque, elles sont écrites
de manière séquentielle, c'est-à-dire les unes
après les autres dans un ordre prédéfini.
✓ Cela permet d'optimiser les performances
d'écriture, car les opérations d'écriture
séquentielle sont généralement plus rapides que
les opérations d'écriture aléatoire.
32. CREATE TABLE Students
(
LastName VARCHAR(15),
FirstName VARCHAR(15),
StudentID INT IDENTITY(100,5)
)
CREATE CLUSTERED INDEX idx_LastName on
Students(LastName)
INSERT INTO Students (LastName, FirstName) VALUES
('Alanzo','Jeff'),
('Carlton','Sara'),
('Bridge','Marla'),
('Tanner','Bill’)
INSERT INTO Students (LastName, FirstName) VALUES
('Cutter','Kim')
https://simplesqltutorials.com/the-b-tree/
36. google/btree: BTree provides a simple, ordered, in-memory data structure for
Go programs. (github.com)
btree package — github.com/google/btree — Go Packages
postgres/btree_bit.c at master · postgres/postgres · GitHub
sqlite/btree.h at b609a79f4a9a0666d51db6f0f7c05e90308ed8c2 · sqlite/sqlite
(github.com)
sqlite/test_btree.c at 37d4ec86bfa78c31732132b7729b8ce0e47da891 ·
sqlite/sqlite (github.com)
ntfstool/btree.cpp at master · thewhiteninja/ntfstool (github.com)
BTreeMap in std::collections — Rust (rust-lang.org)
37. • Temps de recherche efficace.
• Efficacité de stockage.
• Adaptabilité.
• Espace supplémentaire pour l'overhead.
• Performance d'insertion et de suppression.
• Les B-trees sont généralement très efficaces pour les opérations de lecture.
• Les B-trees peuvent être moins efficaces pour les opérations d'écriture (rééquilibrage,
fragmentation, ...).
• Il est important de trouver un équilibre approprié pour le facteur de chargement
maximum.
41. Nouvelle opération d'écriture
|
v
Ajout des données à la Memtable en mémoire
|
v
Écriture des données dans le Write-Ahead Log (WAL)
|
v
Si la Memtable atteint une taille maximale ou un seuil prédéfini:
|
v
Sauvegarde de la Memtable sur le disque en tant que fichier de données temporaire
|
v
Création d'un nouvel emplacement pour une nouvelle Memtable en mémoire
|
v
Processus de compaction périodique
|
v
Fusion des fichiers de données temporaires et des fichiers existants sur le disque
|
v
Suppression des fichiers temporaires
42. Requête de lecture
|
v
Recherche dans la Memtable en mémoire
|
v
Si données trouvées:
|
v
Renvoi des données au client
|
v
Si données non trouvées dans la Memtable:
|
v
Recherche dans les fichiers de données sur le disque
|
v
Parcours séquentiel des fichiers de données
|
v
Combinaison des données provenant de différents niveaux de fichiers (si nécessaire)
|
v
Renvoi des données au client
43. https://disc-projects.bu.edu/compactionary/background.html
✓ La compaction peut être déclenchée de manière
périodique, lorsque la taille de la memtable atteint un
seuil prédéfini, ou en fonction d'autres critères spécifiques
à la mise en œuvre.
✓ Lorsque la compaction est déclenchée, les données de la
memtable en mémoire et des fichiers de données sur le
disque sont fusionnées pour former de nouveaux fichiers
de données.
✓ Les données sont triées et fusionnées de manière à
réduire la fragmentation et à regrouper les données
similaires ensemble.
✓ Pendant la fusion, les doublons peuvent être détectés et
éliminés, garantissant ainsi l'intégrité des données.
✓ De plus, les données obsolètes ou supprimées peuvent
être nettoyées pendant ce processus pour libérer de
l'espace sur le disque.
✓ Une fois la fusion terminée, de nouveaux fichiers de
données sont générés.
✓ Après la compaction, les anciens fichiers de données qui
ne sont plus nécessaires peuvent être supprimés pour
libérer de l'espace sur le disque.
44. Taille des fichiers de données
Intervalle de compaction (Cassandra: compaction_throughput_mb_per_sec.)
Stratégie de compaction (Cassandra: SizeTieredCompactionStrategy,
LeveledCompactionStrategy, etc.)
Politique de rétention des fichiers de données temporaires
Utilisation de la compression des données
Taille de la Memtable en mémoire
48. facebook/rocksdb: A library that provides an embeddable, persistent key-value store for fast
storage. (github.com)
SSTable and Log Structured Storage: LevelDB — igvita.com
The New InfluxDB Storage Engine: Time Structured Merge Tree | InfluxData
indeedeng/lsmtree: A fast key/value store that is efficient for high-volume random access reads and
writes. (github.com)
krestenkrab/hanoidb: Erlang LSM BTree Storage (github.com)
WiredTiger: Log-Structured Merge Trees
lsm_engine — Rust (docs.rs)
leveldb/memtable.cc at main · google/leveldb · GitHub
cassandra/src/java/org/apache/cassandra/io/sstable at trunk · apache/cassandra · GitHub
49. • Performances en écriture élevées.
• Évolutivité.
• Compression des données.
• Complexité de mise en œuvre.
• Besoin de ressources supplémentaires.
• Latence accrue pour les opérations de lecture.
• Performances en écriture vs. Performances en lecture.
• Utilisation des ressources vs. Performances.
• Cohérence vs. Durabilité.
50.
51. Caractéristique
LSM
(Log-Structured Merge-Tree) B-Tree
Principe de fonctionnement
Les données sont d'abord écrites dans un journal en séquence
(WAL), puis fusionnées périodiquement en fichiers de données
plus grands.
Les données sont organisées dans un arbre équilibré avec des
nœuds internes et des feuilles.
Cas d'utilisation
Bases de données distribuées, stockage de journaux (logs),
bases de données NoSQL comme Apache Cassandra et LevelDB.
Bases de données relationnelles, systèmes de fichiers, bases de
données NoSQL comme MongoDB et Couchbase.
Exemples de bases de données Apache Cassandra, LevelDB, RocksDB. PostgreSQL, MySQL, Oracle Database, MongoDB.
Performance en lecture
Peut-être moins efficace en raison de la fragmentation des
fichiers et de la nécessité de fusionner les données lors de la
lecture.
Généralement rapide, surtout pour les requêtes sélectives
ciblant des données spécifiques.
Performance en écriture
Peut être plus efficace en raison de l'écriture séquentielle dans
le journal et de la compaction périodique.
Généralement efficace, mais peut être affectée par la
fragmentation et les opérations de rééquilibrage.
Gestion de la mémoire
Utilise la mémoire pour les Memtables et les caches, peut
nécessiter plus de mémoire pour optimiser les performances.
Nécessite généralement moins de mémoire, mais peut devenir
inefficace pour de grands ensembles de données en mémoire.
Espace disque
Peut utiliser plus d'espace disque en raison de la duplication
des données pendant la fusion et la compaction.
Utilise généralement moins d'espace disque en raison de la
structure plus compacte de l'arbre.
Complexité algorithme
Complexité plus élevée en raison de la compaction périodique
et de la gestion des fichiers de données.
Complexité inférieure en raison de la structure d'arbre équilibré
et des opérations de recherche simples.
52. Data structure for file management
application (B-Tree)
Image cache using B-Tree