Làm thế nào chúng ta có thể lập chỉ mục trong mongodb?
Một chỉ mục trong MongoDB tương tự như cách các chỉ mục hoạt động trong các hệ thống cơ sở dữ liệu khác. Các chỉ mục được áp dụng ở cấp bộ sưu tập và có thể lưu trữ giá trị của một trường hoặc tập hợp trường cụ thể, được sắp xếp theo giá trị của trường Show Tại sao việc lập chỉ mục lại quan trọng trong MongoDB? Các chỉ mục trong MongoDB giúp tránh phải thực hiện quét bộ sưu tập, yêu cầu quét mọi tài liệu trong bộ sưu tập để tìm kết quả phù hợp với truy vấn của bạn (xem. tốn thời gian và nguồn lực). Với các chỉ mục phù hợp, bạn có thể truy vấn hiệu quả hơn vì số lượng tài liệu bị hạn chế ngay từ đầu Mặc dù có thể lưu trữ rất nhiều thông tin trong cơ sở dữ liệu MongoDB, nhưng bạn cần có một chiến lược lập chỉ mục hiệu quả để lấy thông tin bạn cần từ đó một cách nhanh chóng và hiệu quả. Trong hướng dẫn này, tôi sẽ tìm hiểu một số điều cơ bản về cách sử dụng các chỉ mục MongoDB với các truy vấn đơn giản, bỏ qua các bản cập nhật và phần chèn Đây là một cách tiếp cận thực tế chỉ với đủ lý thuyết để cho phép bạn thử các ví dụ. Mục đích là cho phép người đọc chỉ sử dụng shell, mặc dù nó dễ dàng hơn rất nhiều trong GUI MongoDB mà tôi đã sử dụng, Studio 3T Bạn không có thời gian để làm theo các ví dụ? Khi MongoDB nhập dữ liệu của bạn vào một bộ sưu tập, nó sẽ tạo một khóa chính được thực thi bởi một chỉ mục Nhưng nó không thể đoán các chỉ mục khác mà bạn cần vì không có cách nào nó có thể dự đoán loại tìm kiếm, sắp xếp và tổng hợp mà bạn sẽ muốn thực hiện trên dữ liệu này Nó chỉ cung cấp một mã định danh duy nhất cho mỗi tài liệu trong bộ sưu tập của bạn, mã này được giữ lại trong tất cả các chỉ mục khác. MongoDB không cho phép đống. – dữ liệu chưa được lập chỉ mục được liên kết với nhau chỉ bằng con trỏ tiến và lùi MongoDB cho phép bạn tạo các chỉ mục bổ sung tương tự như thiết kế của các chỉ mục được tìm thấy trong cơ sở dữ liệu quan hệ và những chỉ mục này cần một lượng quản trị nhất định Như với các hệ thống cơ sở dữ liệu khác, có các chỉ mục đặc biệt cho dữ liệu thưa thớt, để tìm kiếm thông qua văn bản hoặc để chọn thông tin không gian Bất kỳ một truy vấn hoặc cập nhật nào thường sẽ chỉ sử dụng một chỉ mục duy nhất nếu có sẵn một chỉ mục phù hợp. Một chỉ mục thường có thể giúp thực hiện bất kỳ hoạt động dữ liệu nào, nhưng điều này không phải lúc nào cũng đúng Bạn có thể muốn thử phương pháp 'súng phân tán' – tạo nhiều chỉ mục khác nhau, để đảm bảo rằng sẽ có một chỉ mục phù hợp – nhưng nhược điểm là mỗi chỉ mục sử dụng tài nguyên và cần được hệ thống duy trì Nếu bạn lạm dụng các chỉ mục, chúng sẽ thống trị các trang bộ nhớ và dẫn đến I/O đĩa quá mức. Một số lượng nhỏ các chỉ số hiệu quả cao là tốt nhất Một bộ sưu tập nhỏ có khả năng phù hợp với bộ đệm nên công việc cung cấp chỉ mục và truy vấn điều chỉnh dường như sẽ có nhiều ảnh hưởng đến hiệu suất tổng thể Tuy nhiên, khi kích thước tài liệu tăng lên và số lượng tài liệu tăng lên, công việc đó bắt đầu. Cơ sở dữ liệu của bạn sẽ mở rộng tốt Để minh họa một số khái niệm cơ bản về chỉ mục, chúng tôi sẽ tải 70.000 khách hàng vào. Mỗi tài liệu ghi lại tên, địa chỉ, số điện thoại, chi tiết thẻ tín dụng và 'ghi chú tệp' của khách hàng. Chúng đã được tạo ra từ các số ngẫu nhiên Việc tải này có thể được thực hiện từ mongoimport hoặc từ một công cụ như Studio 3T Bạn có thể tải dữ liệu thử nghiệm được sử dụng trong bài viết tại đây Trước khi bạn tạo một bộ sưu tập, bạn cần xem xét đối chiếu, cách thực hiện tìm kiếm và sắp xếp (đối chiếu không được hỗ trợ trước MongoDB 3. 4) Khi bạn thấy các chuỗi theo thứ tự, bạn có muốn xem chữ thường được sắp xếp sau chữ hoa hay việc sắp xếp của bạn nên bỏ qua chữ hoa chữ thường? Để biết đối chiếu nào, nếu có, được sử dụng cho bộ sưu tập của bạn, bạn có thể sử dụng lệnh này (ở đây dành cho bộ sưu tập 'Khách hàng' của chúng tôi. ) db.getCollectionInfos({name: 'Customers'}) Điều này cho thấy rằng tôi đã đặt bộ sưu tập Khách hàng với đối chiếu 'en'. Nếu tôi cuộn xuống phần đầu ra của trình bao, tôi sẽ thấy rằng tất cả các chỉ mục MongoDB đều có cùng một đối chiếu, điều này thật tốt Thật không may, bạn không thể thay đổi đối chiếu của một bộ sưu tập hiện có. Bạn cần tạo bộ sưu tập trước khi thêm dữ liệu Đây là cách bạn tạo bộ sưu tập 'Khách hàng' với đối chiếu tiếng Anh. Trong Studio 3T, bạn có thể xác định đối chiếu thông qua giao diện người dùng cũng như IntelliShell tích hợp sẵn Download Studio 3T here to use IntelliShell with auto-completion Đây là tab đối chiếu của cửa sổ 'Thêm đối chiếu mới' có thể truy cập bằng cách nhấp chuột phải vào tên cơ sở dữ liệu và nhấp vào 'Thêm đối chiếu mới…' Bạn có thể đạt được điều tương tự trong IntelliShell bằng lệnh db.createCollection("Customers", {collation:{locale:"en",strength:1}}) Độ mạnh của 1 cung cấp cho bạn tìm kiếm không phân biệt chữ hoa chữ thường và dấu phụ. Điều này có thể không phù hợp với sở thích của bạn Thay vào đó, bạn có thể thêm thông tin đối chiếu vào bất kỳ tìm kiếm, sắp xếp hoặc so sánh chuỗi nào mà bạn thực hiện Theo kinh nghiệm của tôi, nó sẽ gọn gàng hơn, an toàn hơn và dễ thay đổi hơn nếu bạn làm điều đó ở cấp độ Bộ sưu tập. Nếu đối chiếu của một chỉ mục không khớp với đối chiếu của tìm kiếm hoặc sắp xếp mà bạn thực hiện, thì MongoDB không thể sử dụng chỉ mục Nếu bạn đang nhập một tài liệu, tốt nhất là thứ tự tự nhiên của chúng được sắp xếp trước theo đối chiếu được chỉ định của bạn theo thứ tự của thuộc tính được lập chỉ mục phổ biến nhất. Điều này làm cho khóa chính được 'phân cụm' trong đó chỉ mục có thể có ít khối trang hơn để truy cập cho mỗi lần tra cứu khóa chỉ mục và hệ thống sẽ có tỷ lệ truy cập cao hơn nhiều Khi chúng tôi đã tải dữ liệu giả mẫu, chúng tôi có thể xem lược đồ của nó chỉ bằng cách kiểm tra tài liệu đầu tiên db.Customers.find({}).limit(1); Trong Studio 3T, bạn có thể xem nội dung này trong Tab Bộ sưu tập Bây giờ chúng tôi sẽ thực hiện một truy vấn đơn giản đối với cơ sở dữ liệu mới tạo của chúng tôi để tìm tất cả khách hàng có họ là 'Johnston' Chúng tôi muốn thực hiện phép chiếu trên hoặc chọn 'Tên' và 'Họ', được sắp xếp theo 'Họ'. “_id”. NumberInt(0), dòng chỉ có nghĩa là 'vui lòng không trả lại ID' use customers; db.Customers.find({ "Name.Last Name" : "Johnston" }, { "_id" : NumberInt(0), "Name.First Name" : NumberInt(1), "Name.Last Name" : NumberInt(1) }).sort({ "Name.Last Name" : NumberInt(1) }); Sau khi hài lòng rằng truy vấn đang trả về kết quả chính xác, chúng tôi có thể sửa đổi truy vấn để trả về số liệu thống kê thực thi. use customers; use customers; db.Customers.find({ "Name.Last Name" : "Johnston" }, { "_id" : NumberInt(0), "Name.First Name" : NumberInt(1), "Name.Last Name" : NumberInt(1) }).sort({ "Name.Last Name" : NumberInt(1) }).explain("executionStats"); Theo số liệu thống kê thực thi của 'Giải thích', việc này mất 59 Ms trên máy của tôi (ExecutionTimeMillis). Điều này liên quan đến COLLSCAN, nghĩa là không có sẵn chỉ mục, vì vậy mongo phải quét toàn bộ bộ sưu tập Đây không nhất thiết là một điều xấu với một bộ sưu tập nhỏ hợp lý, nhưng khi kích thước tăng lên và nhiều người dùng truy cập dữ liệu hơn, thì bộ sưu tập ít có khả năng phù hợp với bộ nhớ được phân trang và hoạt động của đĩa sẽ tăng lên Cơ sở dữ liệu sẽ không mở rộng tốt nếu nó buộc phải thực hiện một tỷ lệ lớn COLLSCAN. Bạn nên giảm thiểu các tài nguyên được sử dụng bởi các truy vấn chạy thường xuyên Chà, rõ ràng là nếu một chỉ số sẽ giảm thời gian thực hiện, thì nó có khả năng liên quan đến Tên. Họ Hãy bắt đầu với điều đó sau đó, biến nó thành một chỉ số tăng dần khi chúng ta muốn sắp xếp tăng dần db.Customers.createIndex( {"Name.Last Name" : 1 },{ name: "LastNameIndex"} ) Máy của tôi hiện mất 4 Ms (ExecutionTimeMillis). Điều này liên quan đến IXSCAN (quét chỉ mục để lấy khóa), sau đó là FETCH (để truy xuất tài liệu) Chúng tôi có thể cải thiện điều này vì truy vấn phải lấy tên Nếu chúng ta thêm Tên. Tên vào chỉ mục, sau đó công cụ cơ sở dữ liệu có thể sử dụng giá trị trong chỉ mục thay vì có thêm bước lấy nó từ cơ sở dữ liệu db.Customers.dropIndex("LastNameIndex") db.Customers.createIndex( { "Name.Last Name" : 1,"Name.First Name" : 1 }, { name: "LastNameCompoundIndex"} ) Với điều này tại chỗ, truy vấn mất ít hơn 2 Ms Do chỉ mục 'bao phủ' truy vấn, MongoDB có thể khớp với các điều kiện truy vấn và trả về kết quả chỉ bằng các phím chỉ mục; . (Nếu bạn thấy giai đoạn IXSCAN không phải là giai đoạn con của giai đoạn FETCH, thì trong kế hoạch thực hiện, chỉ mục sẽ 'bao phủ' truy vấn. ) Bạn sẽ nhận thấy rằng sắp xếp của chúng tôi là sắp xếp tăng dần rõ ràng, A-Z. Chúng tôi đã chỉ định rằng với 1 là giá trị cho sắp xếp. Điều gì sẽ xảy ra nếu kết quả cuối cùng cần từ Z-A (giảm dần) được chỉ định bởi -1? Điều này có vẻ như tiến bộ. Nhưng nếu bạn có chỉ số sai thì sao? Nếu bạn thay đổi thứ tự của hai trường trong chỉ mục để Tên. Tên đứng trước Tên. Họ, thời gian thực hiện bắn lên tới 140 Ms, một mức tăng rất lớn Điều này có vẻ kỳ lạ vì chỉ mục đã thực sự làm chậm quá trình thực thi để nó mất gấp đôi thời gian so với chỉ mục chính mặc định (từ 40 đến 60 Ms). MongoDB chắc chắn kiểm tra các chiến lược thực thi khả thi để tìm một chiến lược tốt, nhưng trừ khi bạn cung cấp một chỉ mục phù hợp, rất khó để chọn một chiến lược phù hợp Vì vậy, những gì chúng ta đã học được cho đến nay?
Trong ví dụ trước của chúng tôi, chúng tôi đã minh họa một sự thật chung về các chỉ mục MongoDB. nếu trường đầu tiên của chỉ mục không phải là một phần của tiêu chí lựa chọn, thì việc thực hiện truy vấn sẽ không hữu ích Điều gì xảy ra nếu chúng ta có hai tiêu chí, một trong số đó liên quan đến khớp chuỗi trong giá trị? use customers; db.Customers.find({ "Name.Last Name" : "Wiggins", "Addresses.Full Address" : /.*rutland.*/i }); Chúng tôi muốn tìm một khách hàng tên là Wiggins sống ở Rutland. Phải mất 50 Ms mà không có bất kỳ chỉ số hỗ trợ nào Nếu chúng tôi loại trừ tên khỏi tìm kiếm, thời gian thực hiện sẽ tăng gấp đôi ________số 8Nếu bây giờ chúng tôi giới thiệu một chỉ số phức hợp dẫn đầu với tên và sau đó thêm địa chỉ, chúng tôi thấy rằng truy vấn nhanh đến mức 0 Ms đã được ghi lại Điều này là do chỉ mục cho phép MongoDB chỉ tìm 52 Wiggins đó trong cơ sở dữ liệu và thực hiện tìm kiếm chỉ qua những địa chỉ đó. Điều này có vẻ đủ tốt Điều gì xảy ra nếu sau đó chúng ta chuyển đổi hai tiêu chí? Cả hai đều là tiêu chí hợp lệ được chỉ định trong truy vấn, nhưng nếu sử dụng sai tiêu chí thì truy vấn còn tệ hơn là vô dụng đối với giai điệu của 20 Ms Lý do cho sự khác biệt là rõ ràng. Chỉ mục có thể ngăn quá trình quét qua tất cả dữ liệu nhưng không thể giúp tìm kiếm vì nó liên quan đến biểu thức chính quy Có hai nguyên tắc chung ở đây Một tìm kiếm phức tạp sẽ làm giảm các ứng cử viên lựa chọn càng nhiều càng tốt với mục đầu tiên trong danh sách chỉ mục. 'Cardinality' là thuật ngữ được sử dụng cho loại chọn lọc này. Một trường có số lượng thẻ thấp, chẳng hạn như giới tính ít được chọn lọc hơn so với họ Trong ví dụ của chúng tôi, họ đủ chọn lọc để trở thành lựa chọn rõ ràng cho trường đầu tiên được liệt kê trong chỉ mục, nhưng không có nhiều truy vấn rõ ràng như vậy Tìm kiếm được cung cấp bởi trường đầu tiên trong chỉ mục có thể sử dụng phải là SARGable. Đây là cách viết tắt để nói rằng trường chỉ mục phải là Search ARGumentable Trong trường hợp tìm kiếm từ 'rutland', cụm từ tìm kiếm không liên quan trực tiếp đến nội dung trong chỉ mục và thứ tự sắp xếp của chỉ mục Chúng tôi có thể sử dụng nó một cách hiệu quả chỉ vì chúng tôi đã sử dụng thứ tự chỉ mục để thuyết phục MongoDB tham gia vào chiến lược tốt nhất để tìm ra 20 'Wiggins' có khả năng xảy ra trong cơ sở dữ liệu và sau đó sử dụng bản sao của địa chỉ đầy đủ trong chỉ mục thay vì chính tài liệu đó Sau đó, nó có thể tìm kiếm rất nhanh hai mươi địa chỉ đầy đủ đó mà không cần phải lấy dữ liệu từ hai mươi tài liệu. Cuối cùng, với khóa chính nằm trong chỉ mục, nó có thể nhanh chóng lấy đúng tài liệu từ bộ sưu tập Hãy thử một truy vấn phức tạp hơn một chút Chúng tôi muốn tìm kiếm họ và địa chỉ email của khách hàng Bộ sưu tập tài liệu của chúng tôi cho phép 'khách hàng' của chúng tôi có một hoặc nhiều địa chỉ email. Đây là trong một mảng nhúng Chúng tôi chỉ muốn tìm một người có họ cụ thể, 'Barker' trong ví dụ của chúng tôi và một địa chỉ email nhất định, '[email được bảo vệ] trong ví dụ của chúng tôi Chúng tôi chỉ muốn trả lại địa chỉ email phù hợp và các chi tiết của nó (khi nó được đăng ký và khi nó trở nên không hợp lệ). Chúng tôi sẽ thực hiện điều này từ trình bao và kiểm tra số liệu thống kê thực thi db.Customers.find({ "Name.Last Name" : "Barker", "EmailAddresses.EmailAddress" : "[email protected]" }, { "_id" : NumberInt(0), "EmailAddresses.$.EmailAddress" : NumberInt(1), "Full Name" : NumberInt(1) }); cái nào mang lại db.createCollection("Customers", {collation:{locale:"en",strength:1}})0 Điều này cho chúng tôi biết rằng Cassie Barker có địa chỉ email [email được bảo vệ] từ ngày 11 tháng 1 năm 2016 đến ngày 25 tháng 1 năm 2018. Khi chúng tôi chạy truy vấn, phải mất 240 ms vì không có chỉ mục hữu ích (nó đã kiểm tra tất cả 40000 tài liệu trong COLLSCAN) Chúng ta có thể tạo một chỉ mục để trợ giúp điều này db.createCollection("Customers", {collation:{locale:"en",strength:1}})1 Chỉ số này đã giảm thời gian thực hiện xuống còn 6ms Chỉ mục Nad là chỉ mục duy nhất có sẵn cho bộ sưu tập chỉ có trên Tên. trường Họ Đối với giai đoạn Đầu vào, chiến lược IXSCAN đã được sử dụng và trả về rất nhanh 33 tài liệu phù hợp, tiếp tục Sau đó, nó lọc các tài liệu phù hợp đó để lấy mảng EmailAddresses cho địa chỉ mà sau đó được trả về trong giai đoạn chiếu. Tổng cộng 3 Ms đã được sử dụng, trái ngược với 70 Ms mà nó đã sử dụng Việc bổ sung các trường khác trong chỉ mục không có tác dụng rõ rệt. Trường chỉ mục đầu tiên đó là trường quyết định thành công Điều gì sẽ xảy ra nếu chúng tôi chỉ muốn biết ai đang sử dụng một địa chỉ email cụ thể? db.createCollection("Customers", {collation:{locale:"en",strength:1}})2 Ở đây, một chỉ mục trên trường Địa chỉ email hoạt động kỳ diệu. Nếu không có chỉ mục phù hợp, nó sẽ thực hiện COLLSCAN, mất khoảng 70 Ms trên máy chủ nhà phát triển của tôi Với chỉ số… db.createCollection("Customers", {collation:{locale:"en",strength:1}})3 … thời gian đã quá nhanh để đo lường Bạn sẽ nhận thấy rằng, để lập chỉ mục cho một trường chứa giá trị mảng, MongoDB tạo khóa chỉ mục cho từng phần tử trong mảng Chúng tôi có thể làm cho nó nhanh hơn nữa nếu chúng tôi cho rằng các địa chỉ email là duy nhất (trong dữ liệu giả mạo này thì không phải như vậy và trong cuộc sống thực, đó là một giả định nguy hiểm. ) Chúng ta cũng có thể sử dụng chỉ mục để 'che' việc truy xuất trường 'Tên đầy đủ', để MongoDB có thể truy xuất giá trị này từ chỉ mục thay vì truy xuất nó từ cơ sở dữ liệu, nhưng tỷ lệ thời gian tiết kiệm được sẽ ít Một lý do khiến truy xuất chỉ mục hoạt động hiệu quả là chúng có xu hướng đạt được tỷ lệ truy cập cao hơn nhiều trong bộ nhớ đệm so với quét toàn bộ bộ sưu tập. Tuy nhiên, nếu tất cả bộ sưu tập có thể nằm gọn trong bộ đệm thì quá trình quét bộ sưu tập sẽ thực hiện gần với tốc độ chỉ mục hơn Hãy xem những tên phổ biến nhất trong danh sách khách hàng của chúng tôi là gì, bằng cách sử dụng tổng hợp. Chúng tôi sẽ cung cấp một chỉ mục về “Tên. Họ" db.createCollection("Customers", {collation:{locale:"en",strength:1}})4 Vì vậy, trong top 10 của chúng tôi, chúng tôi có rất nhiều gia đình Snyder db.createCollection("Customers", {collation:{locale:"en",strength:1}})5 Điều này chỉ mất 8 Ms mặc dù đã thực hiện COLLSCAN vì toàn bộ cơ sở dữ liệu có thể được lưu trong bộ nhớ cache Nó sử dụng cùng một kế hoạch truy vấn ngay cả khi bạn thực hiện tổng hợp trên một trường chưa được lập chỉ mục. (Elisha, Eric, Kim và Lee là những cái tên phổ biến. ) Tôi tự hỏi những cái tên nào có xu hướng thu hút nhiều ghi chú nhất trong hồ sơ của họ? db.createCollection("Customers", {collation:{locale:"en",strength:1}})6 Trong dữ liệu giả mạo của tôi, những người tên là Charisse nhận được nhiều ghi chú nhất. Ở đây chúng tôi biết rằng COLLSCAN là không thể tránh khỏi vì số lượng ghi chú sẽ thay đổi trong hệ thống trực tiếp. Một số cơ sở dữ liệu cho phép lập chỉ mục trên các cột được tính nhưng điều này sẽ không giúp được gì ở đây db.createCollection("Customers", {collation:{locale:"en",strength:1}})7 Hiệu suất của các tập hợp có thể được cải thiện bởi một chỉ mục vì chúng có thể bao gồm tập hợp. Chỉ các nhà khai thác đường ống $match và $sort mới có thể tận dụng trực tiếp một chỉ mục và sau đó chỉ khi chúng xuất hiện ở đầu đường ống kết luận
Đối với các chỉ mục MongoDB, v.v., hãy dùng thử Studio 3T, MongoDB IDE có GUI đầy đủ tính năng cho phép bạn thêm và sửa đổi các chỉ mục, đồng thời chỉ định đối chiếu của chúng, tạo truy vấn trực quan, v.v. Làm cách nào để tạo chỉ mục trong MongoDB?Chỉ mục có thể được tạo bằng cách sử dụng phương thức createIndex . Chỉ mục có thể được tạo trên chỉ một trường hoặc nhiều giá trị trường. Các chỉ mục có thể được tìm thấy bằng cách sử dụng phương thức getIndexes. Các chỉ mục có thể được xóa bằng cách sử dụng dropIndex cho các chỉ mục đơn lẻ hoặc dropIndexes để loại bỏ tất cả các chỉ mục.
Có thể lập chỉ mục trong MongoDB không?MongoDB cung cấp phương thức có tên là createIndex() cho phép người dùng tạo chỉ mục . Khóa xác định trường trên cơ sở bạn muốn tạo chỉ mục và 1 (hoặc -1) xác định thứ tự sắp xếp các chỉ mục này (tăng dần hoặc giảm dần).
Các chỉ mục MongoDB được triển khai như thế nào?Các chỉ mục được triển khai MongoDB sử dụng db. tên bộ sưu tập. createIndex() và đối với mỗi bộ sưu tập mới được tạo, một chỉ mục mặc định được tạo bằng “_id” và chỉ mục này không thể bị xóa. Chúng tôi đã tìm hiểu về nhiều loại chỉ mục có thể được tạo.
Phương pháp nào được sử dụng để tạo chỉ mục trong MongoDB?Phương thức createIndex() được sử dụng để tạo chỉ mục |