2010-12-29 16 views
39
tài liệu

Các MongoDB nói rằngTự động nén không gian đã xóa trong mongodb?

Để nhỏ gọn không gian này, chạy db.repairDatabase() từ vỏ Mongo (lưu ý hoạt động này sẽ chặn và chậm).

trong http://www.mongodb.org/display/DOCS/Excessive+Disk+Space

Tôi tự hỏi làm thế nào để làm cho MongoDB miễn phí xóa không gian đĩa tự động?

p.s. Chúng tôi đã lưu trữ nhiều tác vụ tải xuống trong mongodb, tối đa 20GB và hoàn tất trong nửa giờ.

Trả lời

65

Nói chung, nếu bạn không cần phải thu nhỏ các tệp dữ liệu của mình, bạn không nên thu nhỏ chúng. Điều này là do "phát triển" datafiles của bạn trên đĩa là một hoạt động khá tốn kém và không gian hơn mà MongoDB có thể phân bổ trong các datafiles bạn sẽ có ít phân mảnh hơn.

Vì vậy, bạn nên cố gắng cung cấp càng nhiều không gian đĩa càng tốt cho cơ sở dữ liệu.

Tuy nhiên nếu bạn phải thu nhỏ cơ sở dữ liệu, bạn nên ghi nhớ hai điều.

  1. MongoDB phát triển đó là các file dữ liệu bằng cách tăng gấp đôi vì vậy các datafiles có thể 64MB, sau đó 128MB, vv lên đến 2GB (tại điểm mà nó ngừng tăng gấp đôi lên giữ các tập tin cho đến 2GB.)

  2. Như với hầu hết mọi cơ sở dữ liệu ... để thực hiện các thao tác như thu hẹp, bạn sẽ cần để lập lịch một công việc riêng biệt thành làm như vậy, không có "autoshrink" trong MongoDB. Trong thực tế của các cơ sở dữ liệu NoSQL chính (ghét tên đó) chỉ Riak sẽ tự động sửa. Vì vậy, bạn sẽ cần phải tạo công việc bằng cách sử dụng trình lập lịch biểu của OS để chạy thu nhỏ. Bạn có thể sử dụng một kịch bản bash, hoặc có một công việc chạy một kịch bản php, vv

serverside Javascript

Bạn có thể sử dụng máy chủ bên Javascript để làm co và chạy mà JS qua vỏ Mongo của trên cơ sở thường xuyên thông qua một công việc (như cron hoặc dịch vụ cửa sổ lịch) ...

Giả sử một bộ sưu tập được gọi là foo bạn sẽ tiết kiệm javascript dưới đây vào một tập tin gọi là bar.js và chạy ...

$ mongo foo bar.js 

Các tập tin javascript sẽ giống như ...

// Get a the current collection size. 
var storage = db.foo.storageSize(); 
var total = db.foo.totalSize(); 

print('Storage Size: ' + tojson(storage)); 

print('TotalSize: ' + tojson(total)); 

print('-----------------------'); 
print('Running db.repairDatabase()'); 
print('-----------------------'); 

// Run repair 
db.repairDatabase() 

// Get new collection sizes. 
var storage_a = db.foo.storageSize(); 
var total_a = db.foo.totalSize(); 

print('Storage Size: ' + tojson(storage_a)); 
print('TotalSize: ' + tojson(total_a)); 

này sẽ chạy và trở về một cái gì đó giống như ...

MongoDB shell version: 1.6.4 
connecting to: foo 
Storage Size: 51351 
TotalSize: 79152 
----------------------- 
Running db.repairDatabase() 
----------------------- 
Storage Size: 40960 
TotalSize: 65153 

Run này theo một lịch trình (trong none đỉnh giờ) và bạn tốt để đi.

Capped Collections

Tuy nhiên có một lựa chọn khác, capped collections.

bộ sưu tập Capped được cố định kích thước bộ sưu tập có một hiệu suất tự động FIFO tính năng tuổi-out rất cao (tuổi ra được dựa trên trật tự chèn). Chúng giống như khái niệm "RRD" nếu bạn quen với điều đó.

Ngoài ra, bộ sưu tập được giới hạn tự động, với hiệu suất cao, duy trì thứ tự chèn cho các đối tượng trong bộ sưu tập; đây là rất mạnh mẽ đối với một số trường hợp sử dụng nhất định chẳng hạn như ghi nhật ký.

Về cơ bản, bạn có thể giới hạn kích thước (hoặc số tài liệu in) một bộ sưu tập để nói .. 20GB và một khi giới hạn đó được đạt tới MongoDB sẽ bắt đầu ném ra các hồ sơ lâu đời nhất và thay thế chúng với các mục mới như họ

Đây là một cách tuyệt vời để giữ một lượng lớn dữ liệu, loại bỏ dữ liệu cũ hơn theo thời gian và giữ cùng dung lượng đĩa được sử dụng.

+0

Cám ơn bài đăng tuyệt vời. nếu tôi không thu hẹp các datafiles thì mongod sẽ luôn tốn rất nhiều bộ nhớ, làm thế nào tôi có thể giải quyết nó? –

+0

@Zealot ... Xem câu trả lời của tôi về việc sử dụng bộ nhớ, nó có thể hữu ích. http://stackoverflow.com/questions/4468873/how-to-release-the-caching-which-is-used-by-mongodb/4482465#4482465 –

+0

Tôi hiểu rồi, chúng tôi có bộ nhớ 16 GB và chi phí mongodb 4GB . Vì vậy, tôi có thể không quan tâm về nó. Cảm ơn bạn vì những câu trả lời này. –

24

Tôi có một giải pháp có thể hoạt động tốt hơn làm db.repairDatabase() nếu bạn không đủ khả năng để hệ thống bị khóa hoặc không có gấp đôi bộ nhớ.

Bạn phải đang sử dụng bộ bản sao.

Suy nghĩ của tôi là khi bạn đã xóa tất cả dữ liệu dư thừa đang xáo trộn đĩa, dừng bản sao phụ, xóa thư mục dữ liệu, khởi động và để nó đồng bộ hóa với trình chủ.

Quá trình này tốn thời gian, nhưng chỉ mất vài giây thời gian, khi bạn thực hiện rs.stepDown().

Ngoài ra, điều này không thể tự động được. Nó có thể, nhưng tôi không nghĩ rằng tôi sẵn sàng thử.

+0

Cảm ơn bạn. Điều này làm việc tuyệt vời cho bộ bản sao và chính xác là những gì chúng tôi cần cho một bộ bản sao hết dung lượng. – tcbcw

+2

đây phải là câu trả lời hàng đầu. nó đơn giản và hoạt động trong triển khai trong thế giới thực. – Keeth

+0

Hãy nhận biết, sao chép từ đầu không hoạt động, nếu kích thước oplog quá nhỏ (hoặc bạn có nhiều dữ liệu). Sau đó, đồng bộ hóa ban đầu sẽ mất nhiều thời gian hơn vì khoảng thời gian của oplog và nhân rộng dừng ở đâu đó ở giữa. – scho

8

Chạy db.repairDatabase() sẽ yêu cầu bạn có dung lượng bằng kích thước hiện tại của cơ sở dữ liệu có sẵn trên hệ thống tệp. Điều này có thể khó chịu khi bạn biết rằng các bộ sưu tập còn lại hoặc dữ liệu bạn cần giữ lại trong cơ sở dữ liệu hiện sẽ sử dụng ít không gian hơn những gì được cấp phát và bạn không có đủ không gian để sửa chữa. Nếu bạn có vài bộ sưu tập bạn thực sự cần giữ lại hoặc chỉ muốn một tập hợp con của dữ liệu, thì bạn có thể di chuyển dữ liệu bạn cần để giữ lại một cơ sở dữ liệu mới và thả dữ liệu cũ vào cơ sở dữ liệu cũ. Nếu bạn cần tên cơ sở dữ liệu tương tự, bạn có thể chuyển chúng trở lại thành một db mới bằng cùng tên. Chỉ cần đảm bảo bạn tạo lại bất kỳ chỉ mục nào.

use cleanup_database 
db.dropDatabase(); 

use oversize_database 

db.collection.find({},{}).forEach(function(doc){ 
    db = db.getSiblingDB("cleanup_database"); 
    db.collection_subset.insert(doc); 
}); 

use oversize_database 
db.dropDatabase(); 

use cleanup_database 

db.collection_subset.find({},{}).forEach(function(doc){ 
    db = db.getSiblingDB("oversize_database"); 
    db.collection.insert(doc); 
}); 

use oversize_database 

<add indexes> 
db.collection.ensureIndex({field:1}); 

use cleanup_database 
db.dropDatabase(); 

Hoạt động xuất/nhập/xuất cho cơ sở dữ liệu có nhiều bộ sưu tập có khả năng đạt được kết quả tương tự nhưng tôi chưa thử nghiệm.

Cũng như chính sách, bạn có thể giữ bộ sưu tập vĩnh viễn trong cơ sở dữ liệu riêng biệt từ dữ liệu tạm thời/xử lý và chỉ cần thả cơ sở dữ liệu xử lý sau khi hoàn thành công việc của bạn.Vì MongoDB là lược đồ ít hơn, không có gì ngoại trừ các chỉ mục sẽ bị mất và db và các bộ sưu tập của bạn sẽ được tạo lại khi các chèn cho các tiến trình chạy tiếp theo. Chỉ cần đảm bảo công việc của bạn bao gồm việc tạo bất kỳ chỉ mục nào vào thời điểm thích hợp.

4

Nếu bạn đang sử dụng replica sets, không có sẵn khi câu hỏi này được viết ban đầu, thì bạn có thể thiết lập quy trình tự động khôi phục dung lượng mà không gây ra sự cố hoặc gián đoạn đáng kể về hiệu suất.

Để làm như vậy, bạn tận dụng khả năng đồng bộ hóa ban đầu tự động của một phụ trong bộ bản sao. Để giải thích: nếu bạn tắt một tệp phụ, hãy xóa các tệp dữ liệu của nó và khởi động lại, tệp thứ cấp sẽ đồng bộ hóa lại từ đầu từ một trong các nút khác trong tập hợp (theo mặc định nó chọn nút gần nhất bằng cách xem phản hồi ping lần). Khi sự đồng bộ hóa này xảy ra, tất cả dữ liệu được viết lại từ đầu (bao gồm các chỉ mục), thực hiện tương tự như một sửa chữa và không gian đĩa nó được khai hoang.

Bằng cách chạy ứng dụng này trên thứ hai (và sau đó từ bỏ sơ cấp và lặp lại quy trình), bạn có thể khôi phục hiệu quả dung lượng đĩa trên toàn bộ thiết bị với sự gián đoạn tối thiểu. Bạn cần phải cẩn thận nếu bạn đang đọc từ thứ hai, vì điều này sẽ mất thứ cấp trong vòng quay cho một thời gian dài. Bạn cũng muốn đảm bảo rằng cửa sổ oplog của bạn đủ để thực hiện việc đồng bộ hóa thành công, nhưng đó thường là điều bạn muốn đảm bảo cho dù bạn có thực hiện điều này hay không.

Để tự động quá trình này, bạn chỉ cần chạy tập lệnh để thực hiện tác vụ này vào các ngày riêng biệt (hoặc tương tự) cho từng thành viên trong tập hợp của bạn, tốt nhất là trong thời gian yên tĩnh hoặc cửa sổ bảo trì. Một phiên bản rất ngây thơ của kịch bản này sẽ trông như thế này trong bash:

Chú ý: Đây là cơ bản pseudo code - tính chất minh họa CHỈ - KHÔNG SỬ DỤNG CHO SẢN XUẤT HỆ THỐNG KHÔNG CHỦ YẾU THAY ĐỔI

#!/bin/bash 

# First arg is host MongoDB is running on, second arg is the MongoDB port 

MONGO=/path/to/mongo 
MONGOHOST=$1 
MONGOPORT=$2 
DBPATH = /path/to/dbpath 

# make sure the node we are connecting to is not the primary 
while (`$MONGO --quiet --host $MONGOHOST --port $MONGOPORT --eval 'db.isMaster().ismaster'`) 
do 
    `$MONGO --quiet --host $MONGOHOST --port $MONGOPORT --eval 'rs.stepDown()'` 
    sleep 2 
done  
echo "Node is no longer primary!\n" 

# Now shut down that server 
# something like (assuming user is set up for key based auth and has password-less sudo access a la ec2-user in EC2) 
ssh -t [email protected]$MONGOHOST sudo service mongodb stop 

# Wipe the data files for that server 

ssh -t [email protected]$MONGOHOST sudo rm -rf $DBPATH 
ssh -t [email protected]$MONGOHOST sudo mkdir $DBPATH 
ssh -t [email protected]$MONGOHOST sudo chown mongodb:mongodb $DBPATH 

# Start up server again 
# similar to shutdown something like 
ssh -t [email protected]$MONGOHOST sudo service mongodb start 
Các vấn đề liên quan