Tại sao hướng của chỉ mục lại quan trọng trong MongoDB?


114

Để trích dẫn các tài liệu :

Khi tạo chỉ mục, số được kết hợp với khóa chỉ định hướng của chỉ mục, vì vậy nó phải luôn là 1 (tăng dần) hoặc -1 (giảm dần). Hướng không quan trọng đối với các chỉ mục khóa đơn hoặc đối với truy xuất truy cập ngẫu nhiên nhưng quan trọng nếu bạn đang thực hiện các truy vấn sắp xếp hoặc phạm vi trên các chỉ mục ghép.

Tuy nhiên, tôi thấy không có lý do gì tại sao hướng của chỉ số lại quan trọng đối với các chỉ số ghép. Ai đó có thể vui lòng giải thích thêm (hoặc một ví dụ) không?

Câu trả lời:


111

MongoDB nối khóa ghép theo một cách nào đó và sử dụng nó làm khóa trong BTree.

Khi tìm các mặt hàng đơn lẻ - Thứ tự của các nút trong cây là không liên quan.

Nếu bạn đang trả về một loạt các nút - Các phần tử gần nhau sẽ nằm xuống cùng một nhánh của cây. Các nút càng gần trong phạm vi thì chúng có thể được truy xuất nhanh hơn.

Với một chỉ mục trường duy nhất - Thứ tự sẽ không thành vấn đề. Nếu chúng gần nhau theo thứ tự tăng dần thì chúng cũng sẽ gần nhau theo thứ tự giảm dần.

Khi bạn có khóa ghép - Thứ tự bắt đầu quan trọng.

Ví dụ: nếu khóa là A tăng dần B tăng dần chỉ mục có thể trông giống như sau:

Hàng AB
1 1 1
2 2 6
3 2 7 
4 3 4
5 3 5
6 3 6
7 5 1

Một truy vấn cho A tăng dần B giảm dần sẽ cần phải nhảy xung quanh chỉ mục theo thứ tự để trả về các hàng và sẽ chậm hơn. Ví dụ, nó sẽ trả về Row1, 3, 2, 6, 5, 4, 7

Một truy vấn có phạm vi theo thứ tự giống như chỉ mục sẽ chỉ trả về các hàng một cách tuần tự theo đúng thứ tự.

Tìm một bản ghi trong một BTree mất O (Log (n)) thời gian. Tìm một dãy bản ghi theo thứ tự chỉ là OLog (n) + k trong đó k là số bản ghi cần trả về.

Nếu các bản ghi không theo thứ tự, chi phí có thể cao như OLog (n) * k


1
Hàng kết quả có lẽ phải là 1, 3, 2, 6, 5, 4, 7?
johndodo

Tôi vẫn không thấy lý do gì để nó chậm hơn. Chỉ có thuật toán nên khác (đối với mỗi nhóm giá trị trong A, nó sẽ nhảy đến cuối nhóm và xử lý theo thứ tự ngược lại), nhưng vì các chỉ mục MongoDB nằm trong bộ nhớ nên không ảnh hưởng đáng kể đến tốc độ. Ngoài ra, RDBMS không biết gì về hướng với các chỉ số và tình hình ở đó là khá giống nhau afaik?
johndodo

8
Lý do nó là một hit hiệu suất là vì nó không chỉ là một danh sách tuần tự trong bộ nhớ như ví dụ đơn giản. Nó thực sự là một cây trọng lượng. Nhảy ra khỏi thứ tự sẽ liên quan đến việc đi ngang qua cây một lần nữa. RDMS chắc chắn có thứ tự để lập chỉ mục.
Jared Kells

1
Việc tìm nạp các nút từ một BTree theo thứ tự đơn giản như di chuyển dọc theo từng lá cho đến khi bạn hết và sau đó lên một cấp và xuống nhánh tiếp theo. Nó là O (n) Không đúng thứ tự nó thâm dụng CPU hơn nhiều.
Jared Kells

Cảm ơn đã làm rõ thêm. Tôi đã kiểm tra tài liệu cho các chỉ mục MySQL - thực sự có thể chỉ định hướng chỉ mục, nhưng cài đặt bị bỏ qua.
johndodo

45

Các câu trả lời đơn giản rằng bạn đang tìm kiếm là hướng chỉ quan trọng khi bạn đang sắp xếp vào hai hay nhiều lĩnh vực .

Nếu bạn đang phân loại trên {a : 1, b : -1}:

Chỉ mục {a : 1, b : 1}sẽ là chậm hơn chỉ mục{a : 1, b : -1}


1
@MarkPieszak vì toàn bộ loại sẽ phải được thực hiện trong bộ nhớ làm cho chỉ số vô dụng
Sammaye

@Sammaye Tôi nghĩ đó là ý kiến ​​đúng, mặc dù tôi không chắc rằng đó là toàn bộ . Tôi sẽ phải xem cách triển khai để biết nó thực sự hoạt động như thế nào, nhưng tôi nghĩ rằng kết quả có thể được sắp xếp lại bởi một đơn lẻ, và sau đó sắp xếp b bổ sung sẽ cần được thực hiện trong bộ nhớ.
Zaid Masud

1
hmm, lạ lần cuối cùng tôi đã kiểm tra mã nó giảm các loại phần do cách phân loại là nhưng meh, có lẽ nó đã thay đổi
Sammaye

Điều gì sẽ xảy ra nếu tôi đang sắp xếp {a: -1, b: -1}, tôi nên có {a: -1, b: -1}chỉ mục hay {a: 1, b: 1}sẽ là đủ.
Hussain

@Hussain trong ví dụ của bạn, {a: 1, b: 1}chỉ mục phải đủ vì việc đảo ngược hoàn toàn một chỉ mục là tốt. ví dụ Index trên {a: 1}có thể được sử dụng cho một sắp xếp trên{a: -1}
Zaid Masud

12

Tại sao lập chỉ mục

Hiểu hai điểm chính.

  1. Trong khi một chỉ mục tốt hơn không có chỉ mục, chỉ mục chính xác tốt hơn nhiều.
  2. MongoDB sẽ chỉ sử dụng một chỉ mục cho mỗi truy vấn, tạo chỉ mục ghép với thứ tự trường thích hợp những gì bạn có thể muốn sử dụng.

Chỉ mục không miễn phí. Họ chiếm bộ nhớ và áp dụng hình phạt hiệu suất khi thực hiện chèn, cập nhật và xóa. Thông thường, lần truy cập hiệu suất là không đáng kể (đặc biệt là so với tăng hiệu suất đọc), nhưng điều đó không có nghĩa là chúng ta không thể thông minh trong việc tạo chỉ mục của mình.

Cách lập chỉ mục

Việc xác định nhóm trường nào nên được lập chỉ mục với nhau là hiểu các truy vấn mà bạn đang chạy. Thứ tự của các trường được sử dụng để tạo chỉ mục của bạn là rất quan trọng. Tin tốt là, nếu bạn đặt sai thứ tự, chỉ mục sẽ không được sử dụng, vì vậy sẽ dễ dàng phát hiện ra bằng cách giải thích.

Tại sao lại sắp xếp

Các truy vấn của bạn có thể cần Sắp xếp. Nhưng sắp xếp có thể là một hoạt động tốn kém, vì vậy điều quan trọng là phải coi các trường bạn đang sắp xếp giống như trường mà bạn đang truy vấn. Vì vậy, nó sẽ nhanh hơn nếu nó có chỉ mục. Tuy nhiên, có một điểm khác biệt quan trọng, trường mà bạn sắp xếp phải là trường cuối cùng trong chỉ mục của bạn. Ngoại lệ duy nhất cho quy tắc này là nếu trường cũng là một phần của truy vấn của bạn, thì quy tắc phải là cuối cùng không áp dụng.

Cách sắp xếp

Bạn có thể chỉ định một sắp xếp trên tất cả các khóa của chỉ mục hoặc trên một tập hợp con; tuy nhiên, các khóa sắp xếp phải được liệt kê theo thứ tự khi chúng xuất hiện trong chỉ mục. Ví dụ: mẫu khóa chỉ mục {a: 1, b: 1} có thể hỗ trợ sắp xếp trên {a: 1, b: 1} nhưng không hỗ trợ trên {b: 1, a: 1}.

Việc sắp xếp phải chỉ định cùng một hướng sắp xếp (tức là tăng dần / giảm dần) cho tất cả các khóa của nó làm mẫu khóa chỉ mục hoặc chỉ định hướng sắp xếp ngược cho tất cả các khóa của nó làm mẫu khóa chỉ mục. Ví dụ: mẫu khóa chỉ mục {a: 1, b: 1} có thể hỗ trợ sắp xếp trên {a: 1, b: 1} và {a: -1, b: -1} nhưng không hỗ trợ trên {a: -1 , b: 1}.

Giả sử có các chỉ mục sau:

{ a: 1 }
{ a: 1, b: 1 }
{ a: 1, b: 1, c: 1 }

Example                                                    Index Used
db.data.find().sort( { a: 1 } )                            { a: 1 }
db.data.find().sort( { a: -1 } )                           { a: 1 }
db.data.find().sort( { a: 1, b: 1 } )                      { a: 1, b: 1 }
db.data.find().sort( { a: -1, b: -1 } )                    { a: 1, b: 1 }
db.data.find().sort( { a: 1, b: 1, c: 1 } )                { a: 1, b: 1, c: 1 }
db.data.find( { a: { $gt: 4 } } ).sort( { a: 1, b: 1 } )   { a: 1, b: 1 }

Tôi hiểu đó là một ví dụ nhưng nếu có chỉ mục, { a: 1, b: 1, c: 1 }bạn thực sự cần chỉ mục { a: 1}{ a: 1, b: 1}hoặc chỉ mục { a: 1, b: 1, c: 1 }bao gồm tất cả các trường hợp? Nếu truy vấn luôn luôn sử dụng cùng loại: 1 không có các loại trong truy vấn với -1
Lukas Liesis

1
Nếu có nhiều truy vấn chỉ hoạt động trên thuộc tính 'a', thì việc tìm kiếm bằng chỉ mục có thuộc tính 'a' cho công cụ cơ sở dữ liệu sẽ nhanh hơn tìm kiếm theo chỉ mục với 3 thuộc tính 'a', 'b', 'c'. Vì kích thước chỉ mục sẽ tăng lên và số lượng cũng tăng lên. Ví dụ. Nếu có 20 chương trong cuốn sách. Vì vậy, nó là nhanh hơn để đi đến chương 3 và sau đó trang cụ thể. @LukasLiesis
Somnath Muluk
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.