Мої знання баз даних і SQL базуються в більшості на університетських класах. Так чи інакше, я провів кілька місяців (майже рік) в компанії, де працював з базами даних.
Я прочитав кілька книг , і я взяв участь в декількох тренінгах про базах даних , таких як MySQL
, PostgreSQL
, SQLite
, Oracle
а також кілька nonSQL
db
років такі компанії MongoDB
, Redis
, і ElasticSearch
т.д.
Як я вже сказав, я починаючий, маю багато нестачі знань, але сьогодні хтось щось сказав, що суперечить моїм знаходженцям.
Дозволь пояснити. Візьмемо базу даних SQL і створимо просту таблицю Person
з кількома записами всередині:
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
Тепер це частина, на якій я хотів би зосередитись - id
це та INDEX
.
Поки я вважав, що це працює таким чином: коли створюється таблиця, INDEX
це порожній. Коли я додаю новий запис до своєї таблиці INDEX
, перерахунок проводиться на основі деяких алгоритмів. Наприклад:
Групування по одному:
1 ... N
N+1 ... 2N
...
XN+1 ... (X+1)N
так, для мого прикладу з size = 11 elements
і N = 3
це буде так:
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
Отже, коли я використовую запит, SELECT * FROM Person WHERE id = 8
він зробить простий розрахунок 8 / 3 = 2
, тому ми повинні шукати цей об’єкт, group2
і тоді цей рядок буде повернуто:
8 | Hubert | 53
Цей підхід працює в той час, O(k)
коли k << size
. Звичайно, алгоритм впорядкування рядків по групах, безумовно, набагато складніший, але я думаю, що цей простий приклад показує мою точку зору.
Тож зараз я хотів би представити інший підхід, який мені показали сьогодні.
Візьмемо ще раз цю таблицю:
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
Тепер ми створюємо що - щось подібне Hashmap
(насправді, в буквальному сенсі це Hash Map) , який відображає id
до address
рядка з цим ідентифікатором. Скажімо:
id | addr
---------
1 | @0001
2 | @0010
3 | @0011
4 | @0100
5 | @0101
6 | @0110
7 | @0111
8 | @1000
9 | @1001
10 | @1010
11 | @1011
Отже, коли я запускаю запит: SELECT * FROM Person WHERE id = 8
він буде відображатись безпосередньо id = 8
для адреси в пам'яті, і рядок буде повернутий. Звичайно, складність цього є O(1)
.
Тож зараз у мене мало питань.
1. У чому полягають переваги та недоліки обох рішень?
2. Яка з них більш популярна в поточних реалізаціях бази даних? Можливо, різні dbs використовують різні підходи?
3. Чи існує він у dbs, що не є SQL?
Заздалегідь спасибі
ПОРІВНЯЙТЕ
| 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 - кількість записів
Я правий? А як щодо вартості відновлення таблиці B-tree та Hash після кожного вставки / видалення ? У випадку з B-деревом ми повинні змінити деякі вказівники, але у випадку збалансованого b-дерева йому потрібно більше зусиль. Також у випадку таблиці Hash нам потрібно зробити кілька операцій, особливо, якщо наша операція породжує конфлікти .
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.
Звичайно, я знаю, що це набагато набагато складніше. Отже, нарешті, коли я кажу в коді, INDEX
яке з моїх рішень ( 1-е чи 2-е ) ближче до справжнього? А як щодо часу, необхідного для доступу до запису на основі INDEX
. Це насправді O(1)
? З індексом B-дерева це дуже схоже O(log2(N))
. Я правий?
O(1)
вас зрозуміла правильно! Спочатку, здається, ви описуєте індекс B-дерева, але у вас є непорозуміння. Немає розрахунку (поділ на 3 чи що-небудь), він складніший, оскільки дерево має більше рівнів (це дерево, воно має великі, маленькі, менші гілки, ..., а потім залишає :)