2011-09-06 2 views
7

Tôi là một người mới tương đối với MongoDB, nhưng từ những gì tôi đã đọc có nhiều phương pháp khác nhau để tìm kiếm trung bình và tổng các giá trị trong cơ sở dữ liệu MongoDB, với nhiều lợi ích và hạn chế khác nhau.'AVG' và 'SUM' chức năng trong MongoDB, bất kỳ lời khuyên?

Tôi chủ yếu yêu cầu một phương pháp tìm tổng giá trị lựa chọn và mức trung bình của một lựa chọn giá trị, theo phương thức hiệu quả (nhanh) có thể.

Các tài liệu trong bộ sưu tập được truy vấn giống cấu trúc này (với rất nhiều các lĩnh vực khác):

{ 
    "_id": ObjectId('4e650107580fd649e5000005'), 
    "date_added": ISODate("2011-09-05T00:00:00Z"), 
    "value": 1500 
} 

Precalculating những thứ như tiền, trong ứng dụng của tôi, không phải lúc nào có thể, bởi vì việc lựa chọn các giá trị cho được tổng hợp có thể thay đổi (dựa trên phạm vi ngày - ví dụ: giữa ngày bắt đầu và ngày kết thúc, mức trung bình là gì). Đây là một vấn đề tương tự với trung bình tính toán trước.

Từ những gì tôi đã đọc, MapReduce chắc chắn không phải là lý tưởng cho tra cứu thời gian thực (tức là theo yêu cầu), do đó dường như cũng nằm ngoài câu hỏi.

Tại thời điểm tôi đang truy vấn bộ sưu tập theo cách này: (lưu ý: đây là sử dụng pymongo)

response = request.db['somecollection'].find(
    { 
     'date_added': { 
      '$gte': date_start, 
      '$lte': date_end 
     } 
    }, 
    { 
     'value':1 
    } 
).limit(500) 

Sau đó làm việc tính bằng Python sử dụng một vòng lặp for qua các phản ứng. Giới hạn 500 kết quả là tùy ý, để giữ cho nó trở nên quá chậm. Tôi chỉ lấy giá trị và không có trường nào khác.

Đây có phải là phương pháp hiệu quả nhất để thực hiện phép tính này hay không, hoặc có phương pháp nào khác để thực hiện những gì tôi cần không?

Hãy cẩn thận:

  • tôi không thể sử dụng chức năng group bởi vì tôi có thể sẽ được sử dụng sharding trong tương lai
  • tôi không thể sử dụng MapReduce bởi vì nó là một chức năng mà sẽ được sử dụng trên -e-fly by users
  • Tôi không thể tính toán trước số tiền/giá trị trung bình của tôi vì việc chọn giá trị cho tổng/giá trị trung bình gần như luôn khác nhau
  • Tôi đã xem xét xung quanh stackoverflow và web để thử và tìm giới thiệu về cách làm loại điều, và nó khá bỏ ngỏ

EDIT:

Tôi phải chỉ ra rằng số lượng kết quả trả về từ truy vấn tôi đã đăng ở trên có thể là bất cứ điều gì từ 1 tài liệu đến hàng trăm, nhưng có thể sẽ có số lượng tài liệu trả về tối đa khoảng 150 (trung bình khoảng 60 hoặc 70)

Trả lời

4

Thử bản đồ giảm, có thể không chậm như bạn nghĩ. Tôi đã sử dụng nó để tập hợp thời gian thực trên một số tập hợp dữ liệu lớn, và mặc dù đôi khi nó không phải là sét nhanh, nó thường xuyên hơn. Tốt nhất là nếu bạn có thể lọc xuống kích thước của dữ liệu ban đầu bạn đang tập hợp, ví dụ .:

db.collection.mapReduce(m, r, { query : { year: 2011 } }); 

Nếu bạn cần để tăng tốc hơn nữa, xem xét phân phối dữ liệu qua một cụm sharded.Sau đó, quá trình giảm bản đồ có thể được chia tỷ lệ trên nhiều phân đoạn chạy song song.

+0

Tôi chắc chắn sẽ thử nghiệm nhiều hơn với MapReduce. Tôi biết nó sẽ khác nhau giữa các tập dữ liệu/truy vấn/vv, nhưng trong trường hợp của bạn là nó đủ nhanh để không thực sự đáng chú ý cho người dùng (tức là dưới nửa giây)? – johneth

+0

Thay đổi giữa 500-5000ms, nhưng một số bộ dữ liệu khá lớn (100M + tài liệu), vì vậy cần chỉ báo bận/tiến trình, nhưng đủ nhanh. Hiệu suất giảm bản đồ cũng sẽ cải thiện khi công cụ JavaScript được nâng cấp từ SpiderMonkey đơn luồng lên V8. –

+0

Ah, điều đó nghe có vẻ hứa hẹn. Hiện tại, tập dữ liệu của tôi rất nhỏ (được đo bằng hàng nghìn, không phải hàng triệu), mặc dù điều này sẽ tăng theo thời gian. – johneth

2

câu trả lời đơn giản là:

  1. Nếu nó có thể precalculate tất cả mọi thứ bạn có thể precalculate.
  2. Nếu bạn cần dữ liệu tổng hợp theo phạm vi ngày và tập hợp nên hoạt động nhanh nhất có thể, sau đó sử dụng ánh xạ/giảm + phân đoạn để phân phối phép tính trên nhiều máy.

Nhưng trong cùng một hướng dẫn MongoDB thời gian nói:

Giá của việc sử dụng MapReduce là tốc độ: nhóm không phải là đặc biệt nhanh chóng, nhưng MapReduce là chậm hơn và không phải được sử dụng trong “thực thời gian. ”Bạn chạy MapReduce như một công việc nền, nó tạo ra một bộ sưu tập kết quả, và sau đó bạn có thể truy vấn bộ sưu tập đó trong thời gian thực .

Vì vậy, có vẻ như mongodb không phải là giải pháp tốt nhất để tập hợp dữ liệu theo thời gian thực.

+0

Tôi chắc chắn tính toán trước tất cả các giá trị tôi có thể. Thật không may tôi bị giới hạn trong một máy, ít nhất là lúc đầu, vì vậy tôi không thể lây lan nó trên nhiều máy. Trong ví dụ của tôi, số tài liệu trả về có ảnh hưởng đến tốc độ đủ để cân nhắc sử dụng MapReduce không? (Tôi đã thêm số tài liệu trung bình được trả lại vào cuối câu hỏi của mình) – johneth

3

MongoDB lưu ý

OK, vì vậy Bản đồ/Giảm và tập hợp có một số vấn đề nghiêm trọng hiện nay.

Báo cáo lớn: phiên bản MongoDB chỉ có thể có một phiên bản "động cơ javascript". Điều này có nghĩa rằng bạn không thể chạy hai Map/Reduces đồng thời trên máy chủ. Và bạn chỉ có một lõi để chạy bản đồ-giảm.

Trong trường hợp của những gì bạn đang làm, về cơ bản, bạn "đang tự tạo" M/R. Nhược điểm là lưu lượng mạng bổ sung. Điều ngược lại là bạn có thể ném thêm lõi vào vấn đề (từ các máy chủ web).

câu hỏi quan trọng của bạn

Tôi không thể precalculate rất nhiều tiền của tôi/trung bình vì việc lựa chọn các giá trị để tổng hợp/trung bình là hầu như luôn luôn khác nhau

Không có chung phương pháp để tối ưu hóa "tất cả có thể" truy vấn. Nếu bạn muốn hệ thống có thể tổng hợp và tổng hợp theo mọi trường cho mọi phạm vi, thì cuối cùng bạn sẽ tìm thấy một tập hợp các trường/phạm vi quá lớn.

Cách để "giải quyết" điều này là giảm tập hợp các trường và phạm vi.

Vì vậy, hãy giữ các bộ đếm hàng ngày/hàng giờ và cộng lại các bộ đếm đó. Ít nhất bạn cũng giảm số lượng tài liệu cần quét để trả lời truy vấn của mình.

1

MongoDB được dự kiến ​​nhận các hàm tổng hợp gốc cho những thứ như sum/avg/min/max trong phiên bản 2.1.1 (hiện được dự kiến ​​là ngày 1 tháng 11 năm 2011). Để biết thêm chi tiết và trạng thái, hãy xem sự cố tại: https://jira.mongodb.org/browse/SERVER-447