2015-03-17 14 views
6

Tôi có trang web sử dụng MongoDB để lưu trữ và truy xuất các số đo khác nhau. Đột nhiên, trong một số thời điểm, trang web của tôi trở nên quá chậm chạp, nó trở nên không sử dụng được. Hóa ra, cơ sở dữ liệu của tôi là thủ phạm.MongoDB: Truy vấn chậm, ngay cả với chỉ mục

Tôi đã tìm kiếm và không tìm thấy giải pháp nào cho vấn đề của mình, và tôi xin lỗi vì tôi khá mới với MongoDB và kéo tóc của tôi ra vào lúc này.

Phiên bản MongoDB tôi đang sử dụng là 2.4.6, trên máy ảo có RAM 20 GB, chạy máy chủ Ubuntu 12.04. Không có bản sao hoặc thiết lập sharding.

Thứ nhất, tôi đặt mức profiling tôi để 2 và nó cho thấy các truy vấn chậm nhất:

db.system.profile.find().sort({"millis":-1}).limit(1).pretty() 
{ 
     "op" : "query", 
     "ns" : "station.measurement", 
     "query" : { 
       "$query" : { 
         "e" : { 
           "$gte" : 0 
         }, 
         "id" : "180" 
       }, 
       "$orderby" : { 
         "t" : -1 
       } 
     }, 
     "ntoreturn" : 1, 
     "ntoskip" : 0, 
     "nscanned" : 3295221, 
     "keyUpdates" : 0, 
     "numYield" : 6, 
     "lockStats" : { 
       "timeLockedMicros" : { 
         "r" : NumberLong(12184722), 
         "w" : NumberLong(0) 
       }, 
       "timeAcquiringMicros" : { 
         "r" : NumberLong(5636351), 
         "w" : NumberLong(5) 
       } 
     }, 
     "nreturned" : 0, 
     "responseLength" : 20, 
     "millis" : 6549, 
     "ts" : ISODate("2015-03-16T08:57:07.772Z"), 
     "client" : "127.0.0.1", 
     "allUsers" : [ ], 
     "user" : "" 
} 

Tôi chạy truy vấn cụ thể với .explain() và có vẻ như, nó sử dụng chỉ số như mong muốn, nhưng nó mất quá lâu. Tôi cũng chạy cùng một truy vấn trên máy chủ khác của tôi, máy chủ yếu hơn đáng kể và rút ra kết quả như một nhà vô địch trong một giây.

> db.measurement.find({"id":"180", "e":{$gte:0}}).sort({"t":-1}).explain() 
{ 
     "cursor" : "BtreeCursor id_1_t_-1_e_1", 
     "isMultiKey" : false, 
     "n" : 0, 
     "nscannedObjects" : 0, 
     "nscanned" : 660385, 
     "nscannedObjectsAllPlans" : 1981098, 
     "nscannedAllPlans" : 3301849, 
     "scanAndOrder" : false, 
     "indexOnly" : false, 
     "nYields" : 7, 
     "nChunkSkips" : 0, 
     "millis" : 7243, 
     "indexBounds" : { 
       "id" : [ 
         [ 
           "180", 
           "180" 
         ] 
       ], 
       "t" : [ 
         [ 
           { 
             "$maxElement" : 1 
           }, 
           { 
             "$minElement" : 1 
           } 
         ] 
       ], 
       "e" : [ 
         [ 
           0, 
           1.7976931348623157e+308 
         ] 
       ] 
     }, 
     "server" : "station:27017" 
} 

Tiếp theo, tôi nhìn vào các chỉ số của đo bộ sưu tập và nó trông tốt với tôi:

> db.measurement.getIndexes() 
[ 
     { 
       "v" : 1, 
       "key" : { 
         "_id" : 1 
       }, 
       "ns" : "station.measurement", 
       "name" : "_id_" 
     }, 
     { 
       "v" : 1, 
       "key" : { 
         "t" : 1 
       }, 
       "ns" : "station.measurement", 
       "name" : "t_1" 
     }, 
     { 
       "v" : 1, 
       "key" : { 
         "id" : 1, 
         "d" : 1, 
         "_id" : -1 
       }, 
       "ns" : "station.measurement", 
       "name" : "id_1_d_1__id_-1" 
     }, 
     { 
       "v" : 1, 
       "key" : { 
         "id" : 1, 
         "t" : -1, 
         "e" : 1 
       }, 
       "ns" : "station.measurement", 
       "name" : "id_1_t_-1_e_1" 
     }, 
     { 
       "v" : 1, 
       "key" : { 
         "id" : 1, 
         "t" : -1, 
         "e" : -1 
       }, 
       "ns" : "station.measurement", 
       "name" : "id_1_t_-1_e_-1" 
     } 
] 

Đây cũng là phần còn lại của thông tin thu thập của tôi:

> db.measurement.stats() 
{ 
     "ns" : "station.measurement", 
     "count" : 157835456, 
     "size" : 22377799512, 
     "avgObjSize" : 141.77929395027692, 
     "storageSize" : 26476834672, 
     "numExtents" : 33, 
     "nindexes" : 5, 
     "lastExtentSize" : 2146426864, 
     "paddingFactor" : 1.0000000000028617, 
     "systemFlags" : 0, 
     "userFlags" : 0, 
     "totalIndexSize" : 30996614096, 
     "indexSizes" : { 
       "_id_" : 6104250656, 
       "t_1" : 3971369360, 
       "id_1_d_1__id_-1" : 8397896640, 
       "id_1_t_-1_e_1" : 6261548720, 
       "id_1_t_-1_e_-1" : 6261548720 
     }, 
     "ok" : 1 
} 

Tôi đã thử thêm chỉ mục mới, sửa chữa toàn bộ cơ sở dữ liệu, reindex. Tôi đang làm gì sai? Tôi thực sự đánh giá cao sự giúp đỡ khi tôi tuyệt vọng chạy ra khỏi ý tưởng.

UPDATE 1:

tôi bổ sung thêm hai chỉ số theo đề nghị của Neil Lunn, một số các truy vấn là một Lot nhanh hơn:

{ 
       "v" : 1, 
       "key" : { 
         "id" : 1, 
         "e" : 1, 
         "t" : -1 
       }, 
       "ns" : "station.measurement", 
       "name" : "id_1_e_1_t_-1", 
       "background" : true 
     }, 
     { 
       "v" : 1, 
       "key" : { 
         "id" : 1, 
         "e" : -1, 
         "t" : -1 
       }, 
       "ns" : "station.measurement", 
       "name" : "id_1_e_-1_t_-1", 
       "background" : true 
     } 

Kết quả tôi đã có được thú vị (không chắc chắn mặc dù chúng có liên quan)

Hai truy vấn tiếp theo khác với "id". Xin lưu ý, mỗi truy vấn sử dụng chỉ mục khác nhau, tại sao? Tôi có nên xóa những cái cũ hơn không?

> db.measurement.find({"id":"119", "e":{$gte:0}}).sort({"t":-1}).explain() 
{ 
     "cursor" : "BtreeCursor id_1_t_-1_e_1", 
     "isMultiKey" : false, 
     "n" : 840747, 
     "nscannedObjects" : 840747, 
     "nscanned" : 1047044, 
     "nscannedObjectsAllPlans" : 1056722, 
     "nscannedAllPlans" : 1311344, 
     "scanAndOrder" : false, 
     "indexOnly" : false, 
     "nYields" : 4, 
     "nChunkSkips" : 0, 
     "millis" : 3730, 
     "indexBounds" : { 
       "id" : [ 
         [ 
           "119", 
           "119" 
         ] 
       ], 
       "t" : [ 
         [ 
           { 
             "$maxElement" : 1 
           }, 
           { 
             "$minElement" : 1 
           } 
         ] 
       ], 
       "e" : [ 
         [ 
           0, 
           1.7976931348623157e+308 
         ] 
       ] 
     }, 
     "server" : "station:27017" 
} 

> db.measurement.find({"id":"180", "e":{$gte:0}}).sort({"t":-1}).explain() 
{ 
     "cursor" : "BtreeCursor id_1_e_1_t_-1", 
     "isMultiKey" : false, 
     "n" : 0, 
     "nscannedObjects" : 0, 
     "nscanned" : 0, 
     "nscannedObjectsAllPlans" : 0, 
     "nscannedAllPlans" : 45, 
     "scanAndOrder" : true, 
     "indexOnly" : false, 
     "nYields" : 0, 
     "nChunkSkips" : 0, 
     "millis" : 0, 
     "indexBounds" : { 
       "id" : [ 
         [ 
           "180", 
           "180" 
         ] 
       ], 
       "e" : [ 
         [ 
           0, 
           1.7976931348623157e+308 
         ] 
       ], 
       "t" : [ 
         [ 
           { 
             "$maxElement" : 1 
           }, 
           { 
             "$minElement" : 1 
           } 
         ] 
       ] 
     }, 
     "server" : "station:27017" 
} 

Sự cố có thể ở đâu khác không? Điều gì có thể gây ra "chậm chạp" đột ngột đó? Tôi có một số bộ sưu tập khác, nơi mà các truy vấn cũng đột ngột chậm hơn.

Ồ, và một điều khác. Trên máy chủ khác mà tôi có, các chỉ mục giống như ở đây trước khi tôi thêm các chỉ mục mới. Có, bộ sưu tập nhỏ hơn một chút nhưng nhanh hơn nhiều lần.

+2

Cũng được hình thành như một câu hỏi. Tôi có vẻ như bạn đang quét nhiều mục "t" hơn "e". Là một thử nghiệm, hãy thử thay đổi chỉ mục và thứ tự truy vấn để đặt trọng tâm theo thứ tự vào "e" trước "t". Thay đổi tài liệu đề xuất điều này không nên thay đổi kết quả, nhưng kết quả của bạn sẽ rất thú vị để xem liệu có sự khác biệt hay không. –

+0

Đề xuất thú vị, cảm ơn bạn! Tôi sẽ thêm các chỉ mục mới (id_1_e_1_t_-1 và id_1_e_-1_t_-1) và cho bạn biết về các kết quả này ngay sau khi các chỉ mục xây dựng sẽ mất một thời gian. – Denis

+0

Xin chào, tôi đã xây dựng thành công các chỉ mục đó và thử nghiệm chúng với một số truy vấn. Tôi đã cập nhật câu hỏi của mình với kết quả :) – Denis

Trả lời

0

Sau đó, điểm ở đây là trong cả lựa chọn thứ tự chỉ mục và truy vấn.

Nếu bạn nhìn vào đầu ra trước đó của mình từ .explain(), bạn sẽ thấy rằng có một phạm vi "min/max" trên phần tử "t" trong biểu thức của bạn. Bằng cách "di chuyển đến cuối" của đánh giá, bạn cho phép các phần tử lọc khác quan trọng hơn đối với biểu thức tổng thể (xác định các kết quả có thể ít hơn "e" là yếu tố chính trước khi quét mặc dù "t" về cơ bản là "mọi thứ" .

Đó là một chút DBA, nhưng trong thế giới NoSQL, tôi tin rằng điều này sẽ trở thành một vấn đề lập trình viên.

Về cơ bản, bạn cần phải xây dựng "đường dẫn khớp ngắn nhất" dọc theo các phím đã chọn để quét hiệu quả nhất. Đó là lý do tại sao kết quả thay đổi thực hiện nhanh hơn nhiều.

Các vấn đề liên quan