Hiệu suất đếm MongoDB

Bạn có thể sử dụng ensureIndex() để tăng hiệu suất của phương thức count() trong MongoDB. Để hiểu khái niệm này, chúng ta hãy tạo một bộ sưu tập với tài liệu. Truy vấn để tạo một bộ sưu tập với một tài liệu như sau -

> db.countPerformanceDemo.insertOne({"StudentName":"John","StudentCountryName":"US"});
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5c8ebcf82f684a30fbdfd55f")
}
> db.countPerformanceDemo.insertOne({"StudentName":"Mike","StudentCountryName":"UK"});
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5c8ebd042f684a30fbdfd560")
}
> db.countPerformanceDemo.insertOne({"StudentName":"David","StudentCountryName":"AUS"});
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5c8ebd112f684a30fbdfd561")
}
> db.countPerformanceDemo.insertOne({"StudentName":"Carol","StudentCountryName":"US"});
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5c8ebd1a2f684a30fbdfd562")
}
> db.countPerformanceDemo.insertOne({"StudentName":"Bob","StudentCountryName":"UK"});
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5c8ebd212f684a30fbdfd563")
}

> db.countPerformanceDemo.insertOne({"StudentName":"David","StudentCountryName":"UK"});
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5c8ebd9a2f684a30fbdfd564")
}
> db.countPerformanceDemo.insertOne({"StudentName":"David","StudentCountryName":"US"});
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5c8ebd9e2f684a30fbdfd565")
}

Hiển thị tất cả các tài liệu từ một bộ sưu tập với sự trợ giúp của phương thức find(). Truy vấn như sau -

> db.countPerformanceDemo.find().pretty();

Sau đây là đầu ra -

{
   "_id" : ObjectId("5c8ebcf82f684a30fbdfd55f"),
   "StudentName" : "John",
   "StudentCountryName" : "US"
}
{
   "_id" : ObjectId("5c8ebd042f684a30fbdfd560"),
   "StudentName" : "Mike",
   "StudentCountryName" : "UK"
}
{
   "_id" : ObjectId("5c8ebd112f684a30fbdfd561"),
   "StudentName" : "David",
   "StudentCountryName" : "AUS"
}
{
   "_id" : ObjectId("5c8ebd1a2f684a30fbdfd562"),
   "StudentName" : "Carol",
   "StudentCountryName" : "US"
}
{
   "_id" : ObjectId("5c8ebd212f684a30fbdfd563"),
   "StudentName" : "Bob",
   "StudentCountryName" : "UK"
}
{
   "_id" : ObjectId("5c8ebd9a2f684a30fbdfd564"),
   "StudentName" : "David",
   "StudentCountryName" : "UK"
}
{
   "_id" : ObjectId("5c8ebd9e2f684a30fbdfd565"),
   "StudentName" : "David",
   "StudentCountryName" : "US"
}

Đây là truy vấn để có được dạng đếm () hiệu suất cao -

> db.countPerformanceDemo.ensureIndex({"StudentName":1});
{
   "createdCollectionAutomatically" : false,
   "numIndexesBefore" : 1,
   "numIndexesAfter" : 2,
   "ok" : 1
}

Bây giờ, hãy triển khai phương thức đếm (). Nó đếm các bản ghi với StudentName “David”

> db.countPerformanceDemo.find({"StudentName":"David"}).count();

Sau đây là đầu ra -

3

Nếu bạn, một nhà phát triển phụ trợ, phải mô tả công việc của mình, bạn sẽ nói gì?

Chúng tôi đưa dữ liệu vào cơ sở dữ liệu và lấy lại dữ liệu nhanh nhất có thể.
Cơ sở dữ liệu là nền tảng của chúng tôi. Tại sao chúng ta không nói chuyện thường xuyên hơn về họ? .

Lời khuyên tốt nhất của tôi? . Đơn giản hóa các mô hình dữ liệu của bạn. Đơn giản hóa các mẫu truy cập của bạn

Hiệu suất trong MongoDB

số liệu

Nếu bạn đang sử dụng MongoDB, hai chỉ số này sẽ là người bạn tốt nhất của bạn

  • Tài liệu được quét/Tỷ lệ trả lại
  • IOPS

Tài liệu được quét/trả lại. nó có nghĩa là bạn đang đọc bao nhiêu tài liệu từ đĩa so với số lượng tài liệu bạn thực sự trả lại trong

db.our_collection.find(query).explain("executionStats")
5 hoặc
db.our_collection.find(query).explain("executionStats")
6 của mình. Lý tưởng nhất. cái này phải là 1 (mọi tài liệu đã đọc đều được trả về). Cách duy nhất để có được nó? . Các chỉ mục nằm trong bộ nhớ (hoặc nếu phù hợp), vì vậy MongoDB không phải đọc và lọc chúng từ đĩa

Hiệu suất đếm MongoDB

IOPS. hoạt động I/O mỗi giây. Đó là, hoạt động trên đĩa. Nó tương quan với các tài liệu được quét vì chúng được đọc từ đĩa. Nhưng có nhiều nguồn IOPS hơn, ví dụ như viết.
Đĩa của bạn sẽ cung cấp cho bạn giới hạn đối với IOPS tối đa của bạn. Của chúng tôi là 3000.

Mục tiêu của bạn là giữ IOPS dưới ngưỡng đó và càng thấp càng tốt. Thật khó để biết truy vấn của bạn tiêu tốn bao nhiêu IOPS, nhưng thật dễ dàng để biết tỷ lệ tài liệu được quét/tỷ lệ trả về

Hiệu suất đếm MongoDB

Công cụ

Làm thế nào bạn có thể phân tích lý do tại sao cơ sở dữ liệu của bạn hoạt động như vậy?

MongoDB Profiler
Nếu bạn có đủ khả năng để kích hoạt nó, hãy làm ngay bây giờ. Đó là nguồn thông tin tốt nhất. Chúng tôi sử dụng Atlas MongoDB Profiler và nó đáng giá từng xu.

Hiệu suất đếm MongoDB

Giải thích về công cụ lập kế hoạch
Công cụ lập kế hoạch là chìa khóa để hiểu các kiểu truy cập của bạn.
Có một số cách gọi nó, nhưng bạn có thể bắt đầu bằng

db.our_collection.find(query).explain("executionStats")
7 sau con trỏ của mình.

db.our_collection.find(query).explain()

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Bạn có thể sử dụng add

db.our_collection.find(query).explain("executionStats")
8 để lấy thêm dữ liệu về truy vấn

db.our_collection.find(query).explain("executionStats")

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Có nhiều giai đoạn, nhưng những giai đoạn này là quan trọng nhất

  • COLLSCAN. truy vấn đang quét bộ sưu tập trong đĩa. Khá tệ, vì không có chỉ mục nào bao gồm tìm kiếm, vì vậy MongoDB phải đọc toàn bộ bộ sưu tập
  • IXSCAN. truy vấn đang sử dụng một chỉ mục để lọc. Điều đó không có nghĩa là tất cả các truy vấn được bao phủ bởi chỉ mục, nhưng ít nhất một số phần
  • TÌM VỀ. người lập kế hoạch đang đọc các tài liệu từ bộ sưu tập. Nếu truy vấn của bạn trả về tài liệu, có thể bạn sẽ nhận được giai đoạn FETCH ()

Đây là một ví dụ về một trong những truy vấn của chúng tôi

> db.countPerformanceDemo.find().pretty();
2

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Điều này không tốt vì nó đang quét toàn bộ bộ sưu tập

một cái khác

> db.countPerformanceDemo.find().pretty();
3

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Tại đây, bạn có thể thấy cả hai IXSCAN, được hợp nhất bởi và HOẶC. Sau đó, truy vấn đang tìm nạp tài liệu. Tôi đang đọc truy vấn từ trong ra ngoài.

db.our_collection.find(query).explain("executionStats")
9 được sử dụng để giải quyết một phần của truy vấn và
> db.countPerformanceDemo.find().pretty();
20 cho phần còn lại

Đôi khi bạn sẽ nhận được FETCH ngay sau IXSCAN. điều đó có nghĩa là chỉ mục chỉ bao gồm một phần của bộ lọc. Sau đó, người lập kế hoạch cần đọc tài liệu từ đĩa để kết thúc bộ lọc

Đơn giản hóa truy vấn của bạn

$or

$or là ác quỷ. Bạn, với tư cách là một lập trình viên, đã quen với việc suy nghĩ theo $ors. Bạn thêm một vài đô la, điều kiện của bạn trở nên rõ ràng hơn nhiều. Nhưng đoán xem? . Với mọi điều kiện bạn thêm vào $or, bạn đang thêm một tổ hợp tham số nữa

Người lập kế hoạch giải quyết tất cả những kết hợp đó như thế nào?

Bạn có nhớ

db.our_collection.find(query).explain("executionStats")
7 ở trên không?

> db.countPerformanceDemo.find().pretty();
7

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Các chỉ số được sử dụng?

> db.countPerformanceDemo.find().pretty();
8

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Và đây là một mẹo khác. các chỉ mục lớn hơn có thể bao gồm các truy vấn nhỏ hơn miễn là các trường nằm ở đầu chỉ mục.
Chúng tôi không sử dụng start_date để lọc.

Điều gì sẽ xảy ra nếu tôi thêm $or?

> db.countPerformanceDemo.find().pretty();
9

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Sau đó, sẽ cần 4 kết hợp

{
   "_id" : ObjectId("5c8ebcf82f684a30fbdfd55f"),
   "StudentName" : "John",
   "StudentCountryName" : "US"
}
{
   "_id" : ObjectId("5c8ebd042f684a30fbdfd560"),
   "StudentName" : "Mike",
   "StudentCountryName" : "UK"
}
{
   "_id" : ObjectId("5c8ebd112f684a30fbdfd561"),
   "StudentName" : "David",
   "StudentCountryName" : "AUS"
}
{
   "_id" : ObjectId("5c8ebd1a2f684a30fbdfd562"),
   "StudentName" : "Carol",
   "StudentCountryName" : "US"
}
{
   "_id" : ObjectId("5c8ebd212f684a30fbdfd563"),
   "StudentName" : "Bob",
   "StudentCountryName" : "UK"
}
{
   "_id" : ObjectId("5c8ebd9a2f684a30fbdfd564"),
   "StudentName" : "David",
   "StudentCountryName" : "UK"
}
{
   "_id" : ObjectId("5c8ebd9e2f684a30fbdfd565"),
   "StudentName" : "David",
   "StudentCountryName" : "US"
}
0

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

trường không chuẩn hóa

Nếu bạn thấy mình đang lọc theo nhiều trường trong $or hoặc sắp xếp theo nhiều trường, hãy cân nhắc thêm một trường không chuẩn hóa (dựa trên các trường khác)

Vâng, lời xin lỗi của tôi với hình thức bình thường thứ ba

Hãy tiếp tục đọc, chúng tôi sẽ sớm đưa ra một ví dụ bằng cách sử dụng cái gọi là

> db.countPerformanceDemo.find().pretty();
22

null luôn là giá trị tối thiểu

Đây là một thủ thuật nhỏ, nhưng vẫn hữu ích. Giả sử bạn có một trường nullable và bạn phải lọc (hoặc sắp xếp giảm dần) theo trường đó

Bạn có thể thấy mình đang sử dụng một truy vấn tương tự như thế này

{
   "_id" : ObjectId("5c8ebcf82f684a30fbdfd55f"),
   "StudentName" : "John",
   "StudentCountryName" : "US"
}
{
   "_id" : ObjectId("5c8ebd042f684a30fbdfd560"),
   "StudentName" : "Mike",
   "StudentCountryName" : "UK"
}
{
   "_id" : ObjectId("5c8ebd112f684a30fbdfd561"),
   "StudentName" : "David",
   "StudentCountryName" : "AUS"
}
{
   "_id" : ObjectId("5c8ebd1a2f684a30fbdfd562"),
   "StudentName" : "Carol",
   "StudentCountryName" : "US"
}
{
   "_id" : ObjectId("5c8ebd212f684a30fbdfd563"),
   "StudentName" : "Bob",
   "StudentCountryName" : "UK"
}
{
   "_id" : ObjectId("5c8ebd9a2f684a30fbdfd564"),
   "StudentName" : "David",
   "StudentCountryName" : "UK"
}
{
   "_id" : ObjectId("5c8ebd9e2f684a30fbdfd565"),
   "StudentName" : "David",
   "StudentCountryName" : "US"
}
2

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Nghĩa là, nếu trường rỗng, thì nó sẽ vượt qua bộ lọc. Còn không thì so sánh. Chúng tôi đã sử dụng bộ lọc này để kiểm tra xem một người chơi có thể tham gia trận đấu hay không dựa trên cấp độ của họ và giới hạn cấp độ của trận đấu

Đó là một $ hoặc. Chúng tôi không thích $ors. Điều gì sẽ xảy ra nếu chúng ta so sánh giá trị của mình với null?

{
   "_id" : ObjectId("5c8ebcf82f684a30fbdfd55f"),
   "StudentName" : "John",
   "StudentCountryName" : "US"
}
{
   "_id" : ObjectId("5c8ebd042f684a30fbdfd560"),
   "StudentName" : "Mike",
   "StudentCountryName" : "UK"
}
{
   "_id" : ObjectId("5c8ebd112f684a30fbdfd561"),
   "StudentName" : "David",
   "StudentCountryName" : "AUS"
}
{
   "_id" : ObjectId("5c8ebd1a2f684a30fbdfd562"),
   "StudentName" : "Carol",
   "StudentCountryName" : "US"
}
{
   "_id" : ObjectId("5c8ebd212f684a30fbdfd563"),
   "StudentName" : "Bob",
   "StudentCountryName" : "UK"
}
{
   "_id" : ObjectId("5c8ebd9a2f684a30fbdfd564"),
   "StudentName" : "David",
   "StudentCountryName" : "UK"
}
{
   "_id" : ObjectId("5c8ebd9e2f684a30fbdfd565"),
   "StudentName" : "David",
   "StudentCountryName" : "US"
}
3

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Tức là null luôn là giá trị thấp hơn khi so sánh (ngoại trừ đối tượng MinKey sẽ nói sau)

Truy vấn của chúng tôi có thể được đơn giản hóa bằng cách này

db.our_collection.find(query).explain("executionStats")
0

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Nó hoạt động với $lt và $lte (thấp hơn và thấp hơn hoặc bằng).
Nó cũng hoạt động nếu bạn đang sắp xếp theo thứ tự giảm dần của

> db.countPerformanceDemo.find().pretty();
23
> db.countPerformanceDemo.find().pretty();
24 vì đối tượng có null sẽ ở cuối sắp xếp.

Số lượng rất tốn kém trong MongoDB

Đếm có vẻ là một hoạt động dễ dàng, nhưng nó không phải là. Ngay cả khi bạn có một chỉ mục, MongoDB cần duyệt qua chỉ mục do cách MongoDB xây dựng cây B. chúng không lưu trữ số lá mà cây con có. Vì vậy, họ cần duyệt qua chỉ mục cho đến khi kết thúc

Một lần nữa, nếu bạn đang đếm bằng cách sử dụng truy vấn với $or, thì việc đếm thậm chí còn phức tạp hơn. truy vấn cần tính đến các tài liệu lặp lại có thể

Ví dụ: chúng tôi đã sử dụng số lượng để tính toán vị trí của người chơi trong bảng xếp hạng (truy vấn ban đầu thậm chí còn phức tạp hơn)

db.our_collection.find(query).explain("executionStats")
1

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Nó yêu cầu một số chỉ mục để đếm

db.our_collection.find(query).explain("executionStats")
2

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Làm thế nào chúng ta có thể tránh tính vào một số chỉ mục?

Ví dụ.

> db.countPerformanceDemo.find().pretty();
25
Với trường mới đó, chúng tôi chỉ yêu cầu một chỉ mục duy nhất.
Chỉ mục.

db.our_collection.find(query).explain("executionStats")
3

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Đây được gọi là Mẫu Tóm tắt

Cách xây dựng chỉ mục

Ok, các chỉ mục là công cụ tốt nhất của chúng tôi để giữ cho MongoDB hoạt động hiệu quả nhất có thể. Vì vậy, bước tiếp theo, làm thế nào để chúng ta biết chúng ta nên xây dựng những chỉ mục nào?

Cố vấn hiệu suất

Nếu bạn đang ở trong Atlas, hãy sử dụng Cố vấn hiệu suất

Tại một thời điểm nào đó, bạn sẽ biết hệ thống của mình tốt hơn Trình cố vấn hiệu suất, nhưng đó là một điểm khởi đầu tốt

Sao chép bộ sưu tập sản xuất của bạn và giải thích () nó ở địa phương

Kiểm tra kỹ các chỉ mục của bạn trước khi đưa chúng vào sản xuất. - cần rất nhiều IOPS để xây dựng chúng

  • khi bạn đã xây dựng nó, người lập kế hoạch cũng sẽ tính đến nó, ngay cả khi cuối cùng nó không được sử dụng

Hãy nhớ những gì chúng ta đã nói trước đây

  • COLLSCAN. xấu
  • IXSCAN. tốt
  • TÌM VỀ. tốt nếu đó là bước cuối cùng. Xấu ở giữa. Những người khác mà bạn sẽ thấy
  • ĐẾM. Vâng
  • HỢP NHẤT. ok-ish, có lẽ bạn có thể làm tốt hơn
  • MERGE_COUNT. tốt

Nhân tiện, có các giai đoạn chặn và không chặn, nghĩa là một giai đoạn cần đợi giai đoạn trước đó trước khi có thể bắt đầu tính toán kết quả

ESR. Phạm vi sắp xếp bằng nhau

Bạn đã bao giờ tự hỏi những lĩnh vực nào nên đi đầu tiên trong một chỉ mục?

  • Các trường được lọc theo giá trị bằng ($eq, $in trong một số trường hợp,. ) đi đầu tiên
  • Sau đó, các trường được sử dụng trong giai đoạn sắp xếp. Hãy nhớ rằng chỉ mục phải được tạo theo thứ tự giống như khi bạn sắp xếp
  • Sau đó, các trường được lọc theo một phạm vi ($lt, $lte, $gt,. )

ESR là quy tắc hữu ích nhất mà bạn sẽ tìm thấy để xây dựng các chỉ mục. Bạn nên đọc càng nhiều càng tốt về nó cho đến khi bạn hiểu nó

Bài đăng này của Alex Belilacqua là một viên ngọc quý

phân biệt bằng

Nếu bạn có hai trường sắp được lọc theo $eq, thì trường nào nên thực hiện trước?

Câu trả lời là nó không quan trọng. Bạn không cần phải lo lắng về việc có một cây cân đối hơn

Chỉ cần ghi nhớ quy tắc ESR. Nếu một trong số họ đi vào

> db.countPerformanceDemo.find().pretty();
26 hoặc
> db.countPerformanceDemo.find().pretty();
27, thì nó sẽ đi sau

quá trình tái đầu tư

Xây dựng một chỉ mục là một trong những hoạt động tốn kém nhất. IOPS của bạn sẽ trở nên tồi tệ. Nếu bạn cần làm điều đó trong môi trường sản xuất của mình và bộ sưu tập của bạn đủ lớn, thì chúng tôi khuyên bạn nên sử dụng quy trình cuốn chiếu. Nó bắt đầu xây dựng chỉ mục ở cấp độ thứ cấp, sau đó thăng cấp nó lên cấp độ chính sau khi quá trình xây dựng kết thúc. Bạn sẽ có thể tạo bất kỳ chỉ mục nào ngay cả khi tải cơ sở dữ liệu của bạn cao

Trong Atlas, chỉ cần một cú nhấp chuột

Xóa / Ẩn chỉ mục

Bạn càng có nhiều chỉ số, điều tồi tệ nhất đối với người lập kế hoạch. Trình lập kế hoạch chạy truy vấn thông qua các chỉ mục mà nó có và sau đó chọn cách hứa hẹn nhất

Một lần nữa, đếm khi bạn có nhiều chỉ mục là khá tệ

Đôi khi, bạn không thể xóa một chỉ mục trong sản xuất. Bạn có thể kiểm tra bằng trình hồ sơ của mình nếu nó có thể bị xóa nhưng bạn có thể không 100%. Một truy vấn không thường xuyên có thể khởi chạy COLLSCAN và sau đó bạn sẽ bỏ lỡ chỉ mục đó

May mắn thay, kể từ MongoDB 4. 4 bạn có thể ẩn chỉ mục. Chúng tôi sử dụng chúng để phát hiện những chỉ mục nào chúng tôi có thể xóa một cách an toàn

MongoDB có được đếm nhanh hơn find không?

bộ sưu tập. count() không có tham số sẽ đếm tất cả tài liệu trong bộ sưu tập trong khi db. thu thập. find() không có tham số khớp với tất cả các tài liệu trong một bộ sưu tập và việc thêm vào count() sẽ đếm chúng, vì vậy không có sự khác biệt .

MongoDB có cung cấp hiệu suất cao không?

MongoDB là cơ sở dữ liệu tài liệu NoSQL hàng đầu dành cho các nhà phát triển hiện đại làm việc trên các ứng dụng hiệu năng cao . Với các tài liệu giống như JSON, MongoDB nổi bật với khả năng chia tỷ lệ theo chiều ngang và cân bằng tải, mang đến cho các nhà phát triển sự cân bằng tuyệt vời giữa khả năng tùy chỉnh và khả năng mở rộng.

MongoDB đếm tổng số bản ghi như thế nào?

count() được sử dụng để trả về số lượng tài liệu khớp với truy vấn find(). db. thu thập. Phương thức đếm () không thực hiện thao tác tìm () mà thay vào đó đếm và trả về số lượng kết quả khớp với truy vấn.

Tại sao MongoDB có hiệu suất cao?

MongoDB sử dụng hệ thống khóa để đảm bảo tính nhất quán của tập dữ liệu. Nếu một số hoạt động nhất định đang chạy lâu hoặc hình thành hàng đợi, hiệu suất sẽ giảm khi các yêu cầu và hoạt động chờ khóa