Мои знания баз данных и 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. Какой из них более популярен в современных реализациях баз данных? Может быть, разные БД используют разные подходы?
3. Существует ли он в не-DBS?
заранее спасибо
СРАВНЕНИЕ
| 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-дерева и хеш-таблицы после каждой вставки / удаления ? В случае B-дерева мы должны изменить некоторые указатели, но в случае сбалансированного B-дерева это требует больше усилий. Также в случае с хэш-таблицей мы должны выполнить несколько операций, особенно если наша операция вызывает конфликты .
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 или что-либо еще), он более сложный, так как дерево имеет больше уровней (это дерево, оно имеет большие, маленькие, более мелкие ветви, ... и затем уходит :)