Ma connaissance des bases de données et du SQL est basée dans la plupart des cours universitaires. Quoi qu'il en soit, j'ai passé quelques mois (près d'un an) dans une entreprise, où je travaillais avec des bases de données.
J'ai lu quelques livres et j'ai pris part à quelques formations sur les bases de données telles que MySQL
, PostgreSQL
, SQLite
, Oracle
et aussi peu nonSQL
db
de tels nous MongoDB
, Redis
, ElasticSearch
etc.
Aussi bien que je l'ai dit, je suis débutant, avec beaucoup de manque de connaissances mais aujourd'hui, quelqu'un a dit quelque chose, ce qui est totalement contre les connaissances de mon débutant.
Laissez-moi expliquer. Prenons la base de données SQL et créons une table simple Person
avec quelques enregistrements à l'intérieur:
id | name | age
-----------------
1 | Alex | 24
2 | Brad | 34
3 | Chris | 29
4 | David | 28
5 | Eric | 18
6 | Fred | 42
7 | Greg | 65
8 | Hubert | 53
9 | Irvin | 17
10 | John | 19
11 | Karl | 23
Maintenant, c'est la partie sur laquelle je voudrais me concentrer - id
c'est la INDEX
.
Jusqu'à présent, je pensais que cela fonctionnait de cette façon: quand une table est en cours de création, elle INDEX
est vide. Lorsque INDEX
j'ajoute un nouvel enregistrement à ma table, le est recalculé en fonction de certaines alghortims. Par exemple:
Regroupement un par un:
1 ... N
N+1 ... 2N
...
XN+1 ... (X+1)N
donc, pour mon exemple avec size = 11 elements
et N = 3
ce sera comme ça:
id | name | age
-----------------
1 | Alex | 24 // group0
2 | Brad | 34 // group0
3 | Chris | 29 // group0
4 | David | 28 // group1
5 | Eric | 18 // group1
6 | Fred | 42 // group1
7 | Greg | 65 // group2
8 | Hubert | 53 // group2
9 | Irvin | 17 // group2
10 | John | 19 // group3
11 | Karl | 23 // group3
Donc, lorsque j'utilise une requête, SELECT * FROM Person WHERE id = 8
il fera un calcul simple 8 / 3 = 2
, nous devons donc rechercher cet objet dans group2
, puis cette ligne sera retournée:
8 | Hubert | 53
Cette approche fonctionne dans le temps O(k)
où k << size
. Bien sûr, un algorithme pour organiser les lignes en groupes est certainement beaucoup plus compliqué, mais je pense que cet exemple simple montre mon point de vue.
Alors maintenant, je voudrais présenter une autre approche, qui m'a été montrée aujourd'hui.
Reprenons ce tableau:
id | name | age
-----------------
1 | Alex | 24
2 | Brad | 34
3 | Chris | 29
4 | David | 28
5 | Eric | 18
6 | Fred | 42
7 | Greg | 65
8 | Hubert | 53
9 | Irvin | 17
10 | John | 19
11 | Karl | 23
Maintenant, nous créons quelque chose de similaire à Hashmap
(en fait, c'est littéralement une carte de hachage) qui correspond id
à une address
ligne avec cet identifiant. Disons:
id | addr
---------
1 | @0001
2 | @0010
3 | @0011
4 | @0100
5 | @0101
6 | @0110
7 | @0111
8 | @1000
9 | @1001
10 | @1010
11 | @1011
Alors maintenant, lorsque j'exécute ma requête: SELECT * FROM Person WHERE id = 8
il sera mappé directement id = 8
à l'adresse en mémoire et la ligne sera retournée. Bien sûr, la complexité de cela est O(1)
.
Alors maintenant, j'ai quelques questions.
1. Quelles sont les aventures et les inconvénients des deux solutions?
2. Lequel est le plus populaire dans les implémentations de base de données actuelles? Peut-être que différents dbs utilisent des approches différentes?
3. Existe-t-il dans des dbs nonSQL?
Merci d'avance
COMPARAISON
| B-tree | Hash Table
----------------------------------------------------
---------------- one element -------------------
----------------------------------------------------
SEARCHING | O(log(N)) | O(1) -> O(N)
DELETING | O(log(N)) | O(1) -> O(N)
INSERTING | O(log(N)) | O(1) -> O(N)
SPACE | O(N) | O(N)
----------------------------------------------------
---------------- k elements -------------------
----------------------------------------------------
SEARCHING | k + O(log(N)) | k * O(1) -> k * O(N)
DELETING | k + O(log(N)) | k * O(1) -> k * O(N)
INSERTING | k + O(log(N)) | k * O(1) -> k * O(N)
SPACE | O(N) | O(N)
N - nombre d'enregistrements
Ai-je raison? Qu'en est-il du coût de reconstruction de l'arborescence B et de la table de hachage après chaque insertion / suppression ? En cas d' arbre B, nous devons changer certains pointeurs, mais en cas d' arbre B équilibré, il faut plus d'efforts. De plus, dans le cas d'une table de hachage, nous devons faire peu d'opérations, surtout si notre opération génère des conflits .
Of course, an alghoritm to organise rows in groups is for sure much more complicated but I think this simple example shows my point of view.
Bien sûr, je sais que c'est beaucoup plus compliqué. Alors enfin, quand je dis dans mon code INDEX
laquelle de mes solutions ( 1ère ou 2ème ) est plus proche de cette vraie? Et qu'en est-il du temps nécessaire pour accéder à un enregistrement basé sur INDEX
. C'est vraiment ça O(1)
? Avec l'index B-tree, cela ressemble beaucoup O(log2(N))
. Ai-je raison?
O(1)
vous a bien compris! Dans un premier temps, il semble que vous décriviez un index B-tree mais vous avez un malentendu. Il n'y a pas de calcul (division par 3 ou quoi que ce soit), c'est plus complexe car l'arbre a plus de niveaux (c'est un arbre, il a de grandes, petites, petites branches, ..., et puis laisse :)