SQL INDEX - nó hoạt động như thế nào?


19

Kiến thức về cơ sở dữ liệuSQL 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, Oraclevà cũng có vài nonSQL dbs 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 Personvớ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 - idINDEX.

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 INDEXthì trống. Khi tôi thêm bản ghi mới vào bảng của mình, INDEXnó 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 elementsN = 3nó 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 = 8nó 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 group2và sau đó hàng này sẽ được trả về:

8  | Hubert | 53

nhập mô tả hình ảnh ở đây

Cách tiếp cận này hoạt động trong thời gian O(k)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ạ idtới addresshà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âybả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 .


2
Theo cách thứ hai, bạn đang mô tả một chỉ số băm. Phần về 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 :)
ypercubeᵀᴹ

3
BTrees: en.m.wikipedia.org/wiki/B-tree ngạc nhiên khi không có khóa học thuật toán tại trường đại học của bạn giải thích điều này
Philᵀᴹ

@ypercube Hi, cảm ơn câu trả lời của bạn. Cũng như tôi đã viế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ã INDEXcủ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
ruhungry

@FreshPhilOfSO Tôi đoán (thậm chí nhiều hơn, tôi chắc chắn) đó là một số bài giảng về điều đó. Có lẽ, tôi đã bỏ lỡ điều gì đó ...
ruhungry

ElasticSearch sử dụng các chỉ mục đảo ngược, hoàn toàn khác với B-cây đàn hồi.co / blog / found
Lluis Martinez

Câu trả lời:


12

Về cơ bản, bạn đang mô tả một chỉ mục cây B và một chỉ số băm. Cả hai đều có một vị trí, nhưng cả hai đều phù hợp nhất cho các công việc khác nhau.

Ưu điểm và nhược điểm

Các chỉ số B-tree (và B + -tree) thường được cân bằng. Điều này có nghĩa là việc tìm kiếm một giá trị sẽ luôn mất cùng một khoảng thời gian bất kể nó nằm ở đâu trên cây (O (log n)). Nói chung, số lượng cấp độ trong cây bị hạn chế, vì vậy nó có xu hướng "rộng hơn" chứ không "sâu hơn". Tuy nhiên, đối với các tập dữ liệu nhỏ, chi phí duy trì và sử dụng cây B, tuy nhiên, có thể nhiều hơn là chỉ đọc tất cả các hàng. Các chỉ mục cây B phù hợp với các tập dữ liệu lớn, các tập dữ liệu có độ chọn lọc thấp hoặc các tập dữ liệu mà bạn dự định chọn một phạm vi các đối tượng không chỉ một đối tượng.

Bảng băm là tuyệt vời cho các tập dữ liệu nhỏ. Các chỉ mục băm có số lượng hàm băm được xác định trước, tùy thuộc vào thuật toán băm được sử dụng. Điều này là do thuật toán băm nhất định chỉ có thể tạo ra rất nhiều giá trị băm duy nhất, do đó, nó chỉ được "sâu hơn" chứ không "rộng hơn". Khi công cụ cơ sở dữ liệu tìm thấy nhóm đúng, nó sẽ đi qua tất cả các đối tượng trong nhóm đó để tìm thứ bạn muốn. Với các tập dữ liệu nhỏ, có tính chọn lọc cao, mỗi nhóm chứa một số lượng đối tượng rất nhỏ và được giải quyết khá nhanh. Với các tập dữ liệu lớn hơn, các thùng sẽ đông hơn nhiều. Vì vậy, nếu đối tượng bạn cần nằm trong một cái xô nhỏ hoặc ở gần đầu thùng, nó sẽ trả về khá nhanh. Nếu nó ở cuối một thùng lớn, sẽ mất nhiều thời gian hơn. Chỉ số không cân bằng, do đó hiệu suất ở bất kỳ đâu từ O (1) đến O (n).

Phổ biến

Nói chung, tôi đã chạy qua cây B nhiều nhất. Các chỉ mục bitmap cũng là một tùy chọn khác cho các giá trị có số lượng thẻ thấp (nghĩ là booleans hoặc có thể là giới tính). Điều này sẽ thay đổi tùy thuộc vào công cụ cơ sở dữ liệu của bạn về loại chỉ mục có sẵn.

NoQuery

Cơ sở dữ liệu NoQuery chắc chắn hỗ trợ các chỉ mục. Hầu hết hỗ trợ cây B hoặc một biến thể trên cây B. Hầu hết dường như cũng hỗ trợ các chỉ số băm.


4
Tôi không nghĩ rằng số cấp độ trong cây B + là cố định. Ít nhất là không có trong SQL-Server theo như tôi biết.
ypercubeᵀᴹ

1
Đung. Cây B có thể có bất kỳ số cấp nào, nhưng nó thường bị giới hạn ở 3 hoặc 4. Tôi đã chỉnh sửa câu trả lời của mình.
sarme

Xin chào @sarme. Tôi thực sự thích câu trả lời của bạn. Nó giải thích rất nhiều. Bạn có phiền nếu tôi bắt đầu trả tiền cho câu hỏi này không? Có lẽ ai đó sẽ thêm một cái gì đó thú vị.
ruhungry

1
Bạn có nghĩa là cardinality thấp cho chỉ số bitmap?
Mihai

1
Đúng, cardinality THẤP. Tôi phải ngừng trả lời các câu hỏi ngay trước khi đi ngủ :). Trả lời cập nhật.
sarme

4

Các cuộc phiêu lưu và biến mất của cả hai giải pháp là gì? Giải pháp thứ hai không thể thực hiện quét phạm vi. Nó là tuyệt vời để chọn một ID duy nhất. Nhưng nếu bạn muốn id 3 đến 8 thì sao? Nó phải lấy tất cả các bản ghi riêng lẻ trong thế giới thực không chỉ là các bản ghi O (1) * 6 để lấy. Trong một cơ sở dữ liệu lớn, sản xuất với chỉ mục HashMap, bạn sẽ nhận được các bản ghi trên các trang khác nhau, yêu cầu bạn nhấn đĩa và đọc sáu trang khác nhau vào bộ nhớ.

Trong cấu trúc B-Tree, giống như cách thực hiện tình huống đầu tiên của bạn, các id sẽ được tuần tự trên đĩa và một trang duy nhất có thể giữ id 3 - 8 tăng tốc độ quét phạm vi sẽ giúp truy cập O (log n) .

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? Tôi không có kinh nghiệm lớn trong nhiều cơ sở dữ liệu khác nhau. Tôi biết Sql Server chủ yếu sử dụng B-Plants, nhưng SQl 2014 có một số Chỉ mục Hash mới mà bạn có thể sử dụng trên một số bảng nhất định. Tôi nghe thấy rất nhiều cơ sở dữ liệu No Sql và cơ sở dữ liệu lưu trữ được xây dựng khi truy xuất các bản ghi riêng lẻ cũng sử dụng các chỉ mục băm. Điều này có ý nghĩa đối với bộ nhớ cache vì bạn muốn bản ghi cho người dùng và không cần quét phạm vi.

Có tồn tại trong dbs không? Vâng. Nhìn nhanh vào tài liệu tạo chỉ mục cho postTHERql tôi thấy nó hỗ trợ cả chỉ mục Hash và B-Tree cũng như một vài thứ khác.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.