MongoDB
 sql >> Cơ Sở Dữ Liệu >  >> NoSQL >> MongoDB

MongoDb:cách tạo chỉ mục (tổng hợp) phù hợp cho dữ liệu có nhiều trường có thể tìm kiếm

Tôi sẽ cố gắng giải thích điều này có nghĩa là gì bằng ví dụ. Các chỉ mục dựa trên B-tree không phải là một cái gì đó mongodb cụ thể. Ngược lại, nó là khái niệm khá phổ biến.

Vì vậy, khi bạn tạo một chỉ mục - bạn chỉ cho cơ sở dữ liệu một cách dễ dàng hơn để tìm một thứ gì đó. Nhưng chỉ mục này được lưu trữ ở đâu đó với một con trỏ trỏ đến vị trí của tài liệu gốc. Thông tin này được sắp xếp theo thứ tự và bạn có thể xem nó như cây nhị phân có một đặc tính thực sự tốt:tìm kiếm được giảm từ O(n) (quét tuyến tính) đến O(log(n)) . Điều này nhanh hơn nhiều vì mỗi lần chúng ta cắt bớt một nửa không gian (có khả năng chúng ta có thể giảm thời gian từ 10 ^ 6 xuống còn 20 lần tra cứu). Ví dụ:chúng tôi có một bộ sưu tập lớn với trường {a : some int, b: 'some other things'} và nếu chúng tôi lập chỉ mục nó theo a, chúng tôi sẽ kết thúc với một cấu trúc dữ liệu khác được sắp xếp theo a . Nó trông theo cách này (tôi không có ý nói rằng nó là một bộ sưu tập khác, đây chỉ là để trình diễn):

{a : 1, pointer: to the field with a = 1}, // if a is the smallest number in the starting collection
...
{a : 999, pointer: to the field with a = 990} // assuming that 999 is the biggest field

Vì vậy, ngay bây giờ chúng tôi đang tìm kiếm một trường a =18. Thay vì đi từng phần tử một, chúng tôi lấy một cái gì đó ở giữa và nếu nó lớn hơn thì 18, sau đó chúng tôi chia phần dưới làm đôi và kiểm tra phần tử đó. . Chúng tôi tiếp tục cho đến khi chúng tôi tìm thấy a =18. Sau đó, chúng tôi nhìn vào con trỏ và biết nó, chúng tôi trích xuất trường ban đầu.

Tình hình với chỉ số ghép cũng tương tự (thay vì sắp xếp theo một phần tử, chúng tôi sắp xếp theo nhiều). Ví dụ:bạn có một bộ sưu tập:

{ "item": 5, "location": 1, "stock": 3, 'a lot of other fields' }  // was stored at position 5 on the disk
{ "item": 1, "location": 3, "stock": 1, 'a lot of other fields' }  // position 1 on the disk
{ "item": 2, "location": 5, "stock": 7, 'a lot of other fields' }  // position 3 on the disk
... huge amount of other data
{ "item": 1, "location": 1, "stock": 1, 'a lot of other fields' }  // position 9 on the disk
{ "item": 1, "location": 1, "stock": 2, 'a lot of other fields' }  // position 7 on the disk

và muốn có chỉ mục {"item":1, "location":1, "stock":1}. Bảng tra cứu sẽ trông như thế này (một lần nữa - đây không phải là một bộ sưu tập khác, đây chỉ là để trình diễn):

{ "item": 1, "location": 1, "stock": 1, pointer = 9 }
{ "item": 1, "location": 1, "stock": 2, pointer = 7 }
{ "item": 1, "location": 3, "stock": 1, pointer = 1 }
{ "item": 2, "location": 5, "stock": 7, pointer = 3 }
.. huge amount of other data (but not necessarily here. If item would be one it would be somewhere next to items 1)
{ "item": 5, "location": 1, "stock": 3, pointer = 5 }

Hãy thấy rằng ở đây mọi thứ về cơ bản được sắp xếp theo mục, sau đó theo vị trí và sau đó là con trỏ. Nếu chúng ta có một truy vấn tìm kiếm item = 2, location = 5 and stock = 7 chúng tôi có thể nhanh chóng xác định đâu là tài liệu bằng item = 2 và sau đó theo cùng một cách nhanh chóng xác định vị trí trong số các mục này với location 5 và như vậy.

Và ngay bây giờ là một phần thú vị . Ngoài ra, chúng tôi chỉ tạo một chỉ mục (mặc dù đây là chỉ mục ghép, nó vẫn là một chỉ mục), chúng tôi có thể sử dụng nó để nhanh chóng tìm phần tử

  • chỉ bởi item . Thực sự tất cả những gì chúng ta cần làm chỉ là bước đầu tiên. Vì vậy, không có ích gì để tạo một chỉ mục khác {location:1} vì nó đã được bao phủ bởi chỉ mục kết hợp.
  • ngoài ra, chúng tôi có thể nhanh chóng tìm thấy chỉ theo item and by location (chúng ta chỉ cần 2 bước).

Làm mát 1 chỉ số nhưng giúp chúng ta theo ba cách khác nhau. Nhưng chờ một chút:điều gì sẽ xảy ra nếu chúng ta muốn tìm theo item and stock . Ồ, có vẻ như chúng tôi cũng có thể tăng tốc truy vấn này. Chúng ta có thể trong log (n) tìm thấy tất cả các phần tử với vật phẩm cụ thể và ... ở đây chúng ta phải dừng lại - phép thuật đã kết thúc. Chúng ta cần lặp lại tất cả chúng. Nhưng vẫn khá tốt.

Nhưng nó có thể giúp chúng tôi với các truy vấn khác. Hãy xem một truy vấn theo location có vẻ như đã được đặt hàng. Nhưng nếu bạn nhìn vào nó - bạn sẽ thấy rằng đây là một mớ hỗn độn. Một ở phần đầu và sau đó là một phần cuối. Nó không giúp được gì cho bạn cả.

Tôi hy vọng điều này làm rõ một số điều:

  • tại sao các chỉ mục lại tốt (giảm thời gian từ O (n) xuống O (log (n)))
  • tại sao chỉ mục ghép lại có thể giúp giải quyết một số truy vấn, tuy nhiên chúng tôi chưa tạo chỉ mục trên trường cụ thể đó và trợ giúp với một số truy vấn khác.
  • chỉ mục nào được bao phủ bởi chỉ mục kết hợp
  • tại sao chỉ mục có thể gây hại (nó tạo ra cấu trúc dữ liệu bổ sung cần được duy trì)

Và điều này sẽ nói lên một điều hợp lệ khác:chỉ mục không phải là viên đạn bạc . Bạn không thể tăng tốc tất cả các truy vấn của mình, vì vậy nghe thật ngớ ngẩn khi nghĩ rằng bằng cách tạo chỉ mục trên tất cả các trường MỌI THỨ sẽ cực nhanh.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Mongoose cập nhật / nâng cấp?

  2. Đồng hồ Grunt Serve ném cảnh báo EBUSY qua mongod.lock

  3. Tìm kiếm trong mongo db bằng mongoose regex so với text

  4. mongodb php - cách thực hiện truy vấn giống như INNER JOIN

  5. Kết nối với mongodb bằng mongoose và Fixie (tiện ích bổ sung Heroku)