Kiến thức về cơ sở dữ liệu và SQL của tôi dựa trên hầu hết các lớp học đại học. Nhưng dù sao, tôi đã dành vài tháng (gần một năm) trong một công ty, nơi tôi đang làm việc với cơ sở dữ liệu.
Tôi đã đọc vài cuốn sách và tôi đã tham gia vào vài tập huấn về cơ sở dữ liệu như MySQL
, PostgreSQL
, SQLite
, Oracle
và cũng có vài nonSQL
db
s như chúng tôi MongoDB
, Redis
, ElasticSearch
, vv
Như tôi đã nói, tôi là người ăn xin, với rất nhiều kiến thức thiếu sót nhưng hôm nay, có ai đó đã nói điều gì đó, điều hoàn toàn trái với kiến thức của người bắt đầu.
Hãy để tôi giải thích. Hãy lấy cơ sở dữ liệu SQL và tạo bảng đơn giản Person
với một vài bản ghi bên trong:
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
Bây giờ, đó là phần, tôi muốn tập trung vào - id
là INDEX
.
Cho đến nay, tôi nghĩ rằng nó hoạt động theo cách này: khi một bảng được tạo INDEX
thì trống. Khi tôi thêm bản ghi mới vào bảng của mình, INDEX
nó sẽ được tính toán lại dựa trên một số thuật toán. Ví dụ:
Phân nhóm từng cái một:
1 ... N
N+1 ... 2N
...
XN+1 ... (X+1)N
vì vậy, ví dụ của tôi với size = 11 elements
và N = 3
nó sẽ như thế này:
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
Vì vậy, khi tôi đang sử dụng truy vấn, SELECT * FROM Person WHERE id = 8
nó sẽ thực hiện một số phép tính đơn giản 8 / 3 = 2
, vì vậy chúng tôi phải tìm kiếm đối tượng này group2
và sau đó hàng này sẽ được trả về:
8 | Hubert | 53
Cách tiếp cận này hoạt động trong thời gian O(k)
mà k << size
. Tất nhiên, một thuật toán để tổ chức các hàng theo nhóm chắc chắn phức tạp hơn nhiều nhưng tôi nghĩ ví dụ đơn giản này cho thấy quan điểm của tôi.
Vì vậy, bây giờ, tôi muốn trình bày một cách tiếp cận khác, đã được chỉ ra cho tôi ngày hôm nay.
Hãy lấy lại một lần nữa bảng này:
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
Bây giờ, chúng tôi đang tạo ra một cái gì đó tương tự Hashmap
(trên thực tế, theo nghĩa đen, đó là Bản đồ Hash) ánh xạ id
tới address
hàng với id này. Hãy cùng nói nào:
id | addr
---------
1 | @0001
2 | @0010
3 | @0011
4 | @0100
5 | @0101
6 | @0110
7 | @0111
8 | @1000
9 | @1001
10 | @1010
11 | @1011
Vì vậy, bây giờ, khi tôi đang chạy truy vấn của mình: SELECT * FROM Person WHERE id = 8
nó sẽ ánh xạ trực tiếp id = 8
đến địa chỉ trong bộ nhớ và hàng sẽ được trả về. Tất nhiên sự phức tạp của điều này là O(1)
.
Vì vậy, bây giờ, tôi đã có một vài câu hỏi.
1. Sự ra đời và biến mất của cả hai giải pháp là gì?
2. Cái nào phổ biến hơn trong việc triển khai cơ sở dữ liệu hiện tại? Có thể các dbs khác nhau sử dụng các phương pháp khác nhau?
3. Nó có tồn tại trong dbs không?
Cảm ơn bạn trước
SO SÁNH
| 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 - số lượng hồ sơ
Tôi có đúng không Còn về chi phí xây dựng lại B-cây và bảng Hash sau mỗi lần chèn / xóa ? Trong trường hợp cây B chúng ta phải thay đổi một số con trỏ nhưng trong trường hợp cây b cân bằng, nó cần nhiều nỗ lực hơn. Ngoài ra, trong trường hợp bảng Hash, chúng ta phải thực hiện một vài thao tác, đặc biệt, nếu hoạt động của chúng ta tạo ra xung đột .
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.
Tất nhiên, tôi biết nó phức tạp hơn nhiều. Vì vậy, cuối cùng, khi tôi nói trong mã INDEX
của mình, giải pháp nào của tôi ( thứ 1 hoặc thứ 2 ) gần với giải pháp thực tế này? Và những gì về thời gian cần thiết để truy cập một hồ sơ dựa trên INDEX
. Có thật O(1)
không? Với chỉ số cây B nghe có vẻ giống như O(log2(N))
. Tôi có đúng không
O(1)
bạn đã làm đúng! Theo cách thứ nhất, có vẻ như bạn đang mô tả một chỉ số cây B nhưng bạn có một số hiểu lầm. Không có phép tính (chia cho 3 hoặc bất cứ thứ gì), nó phức tạp hơn vì cây có nhiều cấp độ hơn (đó là cây, nó có nhánh lớn, nhỏ, nhỏ hơn, ..., và sau đó rời đi :)