2010-12-29 9 views
39

MongoDB दस्तावेज़ का कहना है किऑटो mongodb में हटाए गए स्थान कॉम्पैक्ट?

इस अंतरिक्ष, चलाने db.repairDatabase() मोंगो खोल से संकुचित करने के लिए (ध्यान दें कि यह आपरेशन ब्लॉक और धीमी है जाएगा)।

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

में मुझे आश्चर्य है कि कैसे MongoDB मुक्त नष्ट कर दिया डिस्क स्थान स्वचालित रूप से बनाने के लिए?

पेज। हमने 20 जीबी तक, मोंगोडब में कई डाउनलोडिंग कार्य संग्रहीत किए, और इन्हें आधे घंटे में समाप्त कर दिया।

उत्तर

65

सामान्य रूप से यदि आपको अपनी डेटाफाइल को कम करने की आवश्यकता नहीं है तो आपको उन्हें कम नहीं करना चाहिए। ऐसा इसलिए है क्योंकि डिस्क पर आपकी डेटाफाइल "बढ़ती" एक काफी महंगी ऑपरेशन है और अधिक जगह जो मोंगोडीबी डेटाफाइल में आपके पास कम विखंडन आवंटित कर सकती है।

तो, आपको डेटाबेस के लिए जितना संभव हो उतना डिस्क-स्पेस प्रदान करने का प्रयास करना चाहिए।

हालांकि आप डेटाबेस आप मन में दो बातें रखना चाहिए हटना चाहिए।

  1. MongoDB (जो बात यह को दोगुना करना बंद कर देता 2GB तक फाइल को रखने पर।) यह दोगुना तो डाटाफाइलों 64MB, तो 128MB, आदि ऊपर 2GB करने के लिए हो सकता है से डेटा फ़ाइलों है बढ़ता है

  2. अधिकांश डेटाबेस के साथ ... आपको को कम करने जैसे ऑपरेशन पर एक अलग नौकरी निर्धारित करने की आवश्यकता है, ऐसा करने के लिए MongoDB में कोई "ऑटोश्रिंक" नहीं है। प्रमुख नोएसक्यूएल डेटाबेस (उस नाम से नफरत है) के तथ्य में केवल Riak ऑटोश्रिंक होगा। इसलिए, आपको को अपने ओएस के शेड्यूलर को सिकुड़ने के लिए उपयोग करके नौकरी बनाना होगा। आप एक bash स्क्रिप्ट आदि

serverside जावास्क्रिप्ट

इस्तेमाल कर सकते हैं, या एक नौकरी एक php स्क्रिप्ट चलाने, आप छोटा करने के लिए सर्वर साइड जावास्क्रिप्ट का उपयोग कर सकते हैं और चलने वाले मोंगो के खोल के माध्यम से जेएस एक संग्रह foo कहा जाता है मान लिया जाये कि एक नौकरी (क्रॉन या विंडोज़ शेड्यूलिंग सेवा की तरह) के माध्यम से एक नियमित अड्डों ...

पर आप bar.js और चलाने नामक एक फ़ाइल में निम्न जावास्क्रिप्ट की बचत होगी ...

$ mongo foo bar.js 

जावास्क्रिप्ट फ़ाइल कुछ ऐसा दिखाई देगा ...

// 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)); 

यह चलेंगे और की तरह वापसी कुछ ...

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

भागो यह एक समय पर (कोई नहीं चरम अवस्था के दौरान घंटे) और आप जाने के लिए अच्छे हैं।

छाया हुआ संग्रह

लेकिन वहाँ एक अन्य विकल्प, capped collections है।

छाया हुआ संग्रह ठीक संग्रह एक बहुत ही उच्च प्रदर्शन ऑटो फीफो उम्र आउट सुविधा (उम्र बाहर प्रविष्टि आदेश पर आधारित है) है कि आकार। यदि आप उससे परिचित हैं तो वे "आरआरडी" अवधारणा की तरह थोड़ा सा हैं।

इसके अलावा, छाया हुआ संग्रह स्वचालित रूप से, उच्च प्रदर्शन के साथ, संग्रह में वस्तुओं के लिए प्रविष्टि व्यवस्था बनाए रखने; यह कुछ उपयोग मामलों जैसे लॉगिंग के लिए बहुत शक्तिशाली है।

मूल रूप से आप के आकार (या में दस्तावेजों की संख्या) कहने के लिए .. 20GB और एक बार है कि सीमा पार होने पर MongoDB सबसे पुराने रिकॉर्ड बाहर फेंक और उन्हें वे जैसे नए प्रविष्टियों के साथ बदलने के लिए शुरू कर देंगे एक संग्रह सीमित कर सकते हैं अंदर आओ।

यह बड़ी मात्रा में डेटा रखने के लिए एक बड़ा तरीका है, पुराने डेटा को छोड़कर समय के साथ-साथ डिस्क-स्पेस का उपयोग किया जाता है।

+0

के लिए धन्यवाद महान पद। अगर मैं डेटाफाइल को कम नहीं करता हूं तो मोंगोड हमेशा बहुत मेमोरी खर्च करेगा, मैं इसे कैसे हल कर सकता हूं? –

+0

@Zealot ... स्मृति उपयोग पर मेरा उत्तर देखें, यह सहायक हो सकता है। http://stackoverflow.com/questions/4468873/how-to-release-the-caching-which-is-used-by-mongodb/4482465#4482465 –

+0

मुझे मिल गया, हमारे पास 16 जीबी मेमोरी है, और मोंगोडब लागत 4 जीबी है । तो मुझे इसकी परवाह नहीं है। इन उत्तरों के लिए धन्यवाद। –

24

मेरे पास एक और समाधान है जो db.repairDatabase() करने से बेहतर काम कर सकता है यदि आप सिस्टम को लॉक होने के लिए बर्दाश्त नहीं कर सकते हैं, या स्टोरेज को दोगुना नहीं कर सकते हैं।

आपको एक प्रतिकृति सेट का उपयोग करना होगा।

मेरा विचार यह है कि एक बार जब आपने अपनी डिस्क को गोबलिंग करने वाले सभी अतिरिक्त डेटा को हटा दिया है, तो द्वितीयक प्रतिकृति को रोकें, इसकी डेटा निर्देशिका मिटाएं, इसे शुरू करें और इसे मास्टर के साथ पुन: सिंक्रनाइज़ करने दें।

प्रक्रिया समय लेने वाली है, लेकिन जब आप rs.stepDown() करते हैं, तो इसे केवल कुछ ही समय का समय चाहिए।

इसके अलावा इसे स्वचालित नहीं किया जा सकता है। वैसे यह हो सकता है, लेकिन मुझे नहीं लगता कि मैं कोशिश करने के लिए तैयार हूं।

+0

धन्यवाद। यह प्रतिकृति सेट के लिए बहुत ही बढ़िया काम करता है और अंतरिक्ष के बाहर भागने वाले प्रतिकृति सेट के लिए हमें वही चाहिए था। – tcbcw

+2

यह शीर्ष जवाब होना चाहिए। यह आसान है और एक वास्तविक दुनिया तैनाती में काम करता है। – Keeth

+0

ध्यान रखें, स्क्रैच से प्रतिकृति काम नहीं करती है, अगर ओप्लॉग आकार बहुत छोटा है (या आपके पास बहुत अधिक डेटा है)। फिर, शुरुआती सिंकिंग में अधिक समय लगेगा क्योंकि ओप्लोग का समय अवधि और प्रतिकृति कहीं बीच में बंद हो जाती है। – scho

8

रनिंग db.repairDatabase() को यह आवश्यक होगा कि आपके पास फ़ाइल सिस्टम पर उपलब्ध डेटाबेस के वर्तमान आकार के बराबर स्थान हो। यह परेशान हो सकता है जब आप जानते हैं कि डेटाबेस में बनाए रखने के लिए आपको छोड़े गए संग्रह या डेटा को वर्तमान में आवंटित किए गए स्थान से बहुत कम स्थान का उपयोग करना होगा और आपके पास मरम्मत करने के लिए पर्याप्त जगह नहीं है।

एक विकल्प के रूप में यदि आपके पास कुछ संग्रह हैं, तो आपको वास्तव में बनाए रखने की आवश्यकता है या केवल डेटा का सबसेट चाहिए, तो आप उस डेटा को स्थानांतरित कर सकते हैं जिसे आपको नए डेटाबेस में रखने और पुराने को छोड़ने के लिए आवश्यक है। यदि आपको एक ही डेटाबेस नाम की आवश्यकता है तो आप उन्हें उसी नाम से एक नए डीबी में वापस ले जा सकते हैं। बस सुनिश्चित करें कि आप किसी भी इंडेक्स को फिर से बनाते हैं।

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(); 

कई संग्रहों के साथ डेटाबेस के लिए एक निर्यात/ड्रॉप/आयात ऑपरेशन संभवतः एक ही परिणाम प्राप्त करेगा, लेकिन मैंने परीक्षण नहीं किया है।

नीति के रूप में आप अपने क्षणिक/प्रसंस्करण डेटा से अलग डेटाबेस में स्थायी संग्रह रख सकते हैं और अपनी नौकरियों को पूरा करने के बाद बस प्रोसेसिंग डेटाबेस छोड़ सकते हैं।चूंकि मोंगोडीबी स्कीमा-कम है, इसलिए इंडेक्स को छोड़कर कुछ भी नहीं खो जाएगा और प्रक्रियाओं के लिए सम्मिलित होने पर आपके डीबी और संग्रह फिर से बनाए जाएंगे। बस सुनिश्चित करें कि आपकी नौकरियों में उचित समय पर किसी भी नेसैकरी इंडेक्स बनाना शामिल है।

4

यदि आप replica sets का उपयोग कर रहे हैं, जो इस प्रश्न को मूल रूप से लिखा गया था, तब उपलब्ध नहीं थे, तो आप महत्वपूर्ण व्यवधान या प्रदर्शन समस्याओं के बिना स्वचालित रूप से स्थान पुनः प्राप्त करने के लिए एक प्रक्रिया स्थापित कर सकते हैं।

ऐसा करने के लिए, आप प्रतिलिपि सेट में माध्यमिक की स्वत: प्रारंभिक सिंक क्षमताओं का लाभ उठाते हैं। व्याख्या करने के लिए: यदि आप द्वितीयक को बंद करते हैं, तो अपनी डेटा फ़ाइलों को मिटा दें और इसे पुनरारंभ करें, द्वितीयक सेट में दूसरे नोड्स में से किसी एक से स्क्रैच से फिर से सिंक हो जाएगा (डिफ़ॉल्ट रूप से यह पिंग प्रतिक्रिया को देखकर निकटतम नोड को चुनता है बार)। जब यह रेजिंक होता है, तो सभी डेटा स्क्रैच (इंडेक्स समेत) से फिर से लिखे जाते हैं, प्रभावी रूप से एक ही चीज को मरम्मत के रूप में करते हैं, और डिस्क स्पेस को पुनः दावा किया जाता है।

द्वितीयक पर इस चल (और फिर प्राथमिक पद छोड़ने और इस प्रक्रिया को दोहरा) आप को प्रभावी ढंग से न्यूनतम विघटन के साथ पूरे सेट पर डिस्क स्थान को पुनः प्राप्त सकता है। यदि आप सेकेंडरी से पढ़ रहे हैं तो आपको सावधान रहना होगा, क्योंकि यह संभावित रूप से लंबे समय तक घूर्णन से बाहर हो जाएगा। आप यह भी सुनिश्चित करना चाहते हैं कि oplog विंडो सफल राइन्क करने के लिए पर्याप्त है, लेकिन आम तौर पर यह सुनिश्चित करना है कि आप यह सुनिश्चित करना चाहते हैं कि आप ऐसा करते हैं या नहीं।

इस प्रक्रिया को आप बस अधिमानतः अपने शांत समय या रखरखाव विंडो के दौरान, अलग दिनों (या समान) अपने सेट के प्रत्येक सदस्य के लिए पर यह कार्रवाई करने की एक स्क्रिप्ट चलाने की आवश्यकता होगी स्वचालित करने के लिए। इस स्क्रिप्ट का एक बहुत ही भोली संस्करण bash में इस प्रकार दिखाई देगा:

नोट: यह मूलतः छद्म कोड है - निदर्शी प्रयोजनों के लिए केवल - महत्वपूर्ण परिवर्तन के बिना उत्पादन प्रणालियों के लिए उपयोग न

#!/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 
संबंधित मुद्दे