Mongodb နှင့် Data ကြီးများ ( ၁ )

Mongodb နဲ့ ပတ်သက်ပီး အရင်ကတော့ တခါရေးဖူးပါတယ်။ ကြာတော့ ကြာပီ။ အဲ့တုန်းက Mongodb ဆိုတာ ဘာကိုခေါ်သလဲ။ ဘာတွေ လုပ်လို့ရသလဲ လောက်ပဲ ရေးဖြစ်တာ။ ပြောရရင် ကျွန်တော်လဲ CRUD လောက်ပဲ သုံးဖူးရုံလောက်လေး ရှိသေးတာလဲပါတယ်။ Mongodb shell ထဲတောင် မဝင်ဘူးဖူး။  GUI တွေပဲ သုံးလိုက်တာ။ အခု နှစ်ပိုင်းမှာ Mongodb ကို Big data တွေနဲ့ နှဖူးရော ဒူးရော တွေ့တော့ CRUD ထက်ပိုတာတွေ လုပ်ရပါလေရော။ အဲ့ဒါကြောင့် ကိုယ်လုပ်ခဲ့ တာလေးတွေ ကို စာတတန် ပေတတန်နဲ့ ရေးရင်ကောင်းမယ် စိတ်ကူးမိတယ်။ နောက်နှစ်လောက်ရောက်ရင် ကိုယ့်ဘာသာကိုတောင် မေ့သွားရင် မေ့သွားမှ ဆိုတော့ စာလေး ရေးထားပီး ပြန်ဖတ် ကော်ပီလေး ဘာလေး ကူးလို့ရအောင် ပေါ့။ Google မှာ ရှာလို့ မရဘူးလား ဆိုတော့ လဲ ရှာလို့ရပါတယ်။ ဒါပေမယ့် စာလေး ရေးထားတော့ ပြန်ရှာရ ပိုလွယ်တာပေါ့။ နောက်တခုက production ရောက်ရင် လိုအပ်တာလေးတွေ ကြိုလုပ်ထား တော့ cpu နဲ့ memory usage တွေ မတက်အောင်၊ အများကြီး မဟုတ်တောင် server ကြီး လေးမနေအောင် sharing လုပ်ချင်တာလဲ ပါတယ်။ ကျွန်တော် က Mongodb ကို လက်ရှိသုံးနေတော့ Mongodb နဲ့ ပတ်သက်ပီးရေးတာ ဆိုပေမယ့် တခြား db တွေမှာ လဲ တူညီတဲ့ အလုပ်လုပ်ပုံတွေ ရှိပါတယ်။ Index လုပ်တာတွေ repair  လုပ်တာတွေစေတာတွေပေါ့။ အဲ့ဒါကြောင့် အများကြီး မဟုတ်တောင် ကိုယ့်သုံးနေတဲ့ db ပေါ်မှာ performance ပိုကောင်းအောင် လုပ်နိုင်တဲ့ အချက်လေးတွေ သတိထားမိ သွားနိုင်ပါတယ်။ကိုယ်လုပ်ခဲ့ တာတွေပဲ ရေးမှာဆိုတော့ ကိုယ်အတွက် အဆင်ပြေသွားပေမယ့် ပိုကောင်းတာတွေလဲ ရှိနိုင်ပါတယ်။

Indexing

Mongodb က write performance ကောင်းတယ်ဆိုတော့ ကိုယ့် Application တွေက Data velocity များခဲ့ရင်တောင် သင့်တင့်တဲ့ server တခုသုံးရုံနဲ့ ကောင်းကောင်း ကြီး အလုပ်လုပ်ပါတယ်။ ဒါပေမယ့် read ဖို့ အတွက် ကတော့ Indexing လုပ်ပေးရမှအဆင်ပြေမှာပါ။ Index ဆောက်တာတွေကို အဓိက အားဖြင့်က query performance မြှင့်တဲ့နေရာတွေမှာသုံးတာပါ။ Data တွေ ပြန်ထုတ်ရင်လေးနေတာတို့ Search လုပ်ရင်ကြာတာတို့ စသဖြင့်ပေါ့။  ကိုယ့် Collection တစ်ခုရဲ့ Documents  တွေက ၁ ထောင် ၁ သောင်းလောက် ဆို မသိသာပေမယ့် သိန်းနဲ့ သန်းနဲ့ ချီလာပြီဆို လိုလာပါပီ။ Index မပေးထားရင် Mongodb က Collection မှာ ရှိတဲ့ Document တခုတိုင်းကို scan မှာပါ။ အဲ့လိုဆိုရင် တမေ့တမော စောင့် request time out တွေ memory exhausted တွေဖြစ်၊ ကျွန်တော့် code ကမှန်တယ်ရဲ့သားနဲ့ ဘာလို့မရတာလဲ၊ server ကြီးလေးနေတယ် လုပ်ကြပါဦး စသဖြင့် စကားတွေပြောလာရတော့မယ်။ အဲ့လိုတွေမဖြစ်ရလေအောင် ကိုယ့်ဖက်က ကြိုလုပ်လို့ရတာလေးတွေ ကြိုလုပ်ထားဖို့လိုပါတယ်။ ကျွန်တော်က တော့ အများအားဖြင့် query လုပ်မယ့် fields တွေကို Index ပေးထားလိုက်တယ်။
ဥပမာ - person data ပဲထားပါတော့။ သူ့မှာ name, dob, age, gender, nrc_card ရှိတယ်ဆိုပါစို့။ gender နဲ့ query ထုတ်မယ်ဆိုရင် gender ကို index ပေးထားရင် ပိုမြန်ပါတယ်။

db.person.createIndex({ gender: 1 })

နောက်မှာပါတယ့် 1 ကတော့ ascending စီတာပါ။ 1 , -1 ကိုယ့် စီချင်တဲ့ ပုံစံပေးလို့ရပါတယ်။ဒါမှမဟုတ် nrc_card နဲ့ ရှာချင်တယ်ဆိုပါတော့။ nrc_card ရှိတဲ့သူ ဘယ်နှစ်ယောက်ရှိလဲဆိုတာမျိုးပေါ့။

db.person.createIndex({ nrc_card: 1 },{ sparse: true })

ပုံမှန် index ဆောက်လို့ရရဲ့သားနဲ့ ဘာလို့ spares ထည့်ထားလဲ။ အဲ့ဒါကတော့ ကျွန်တော် ရှာဖွေတွေ့ရှိထားတဲ့ အထဲက တခုပေါ့။ Sparse index က documents အကုန်လုံးကို index ထောက်တာမဟုတ်ပဲ သူ့ field ပါတဲ့ documents တွေကိုပဲ index လုပ်ပေးတာပါ။ အဲ့တော့ မပါတဲ့ ဟာတွေ အတွက် skip လုပ်ပေးမှာပါ။ Big Data တွေမှာ တော်တော် အသုံးဝင်ပါတယ်။ နောက်တခုက unique နဲ့တွဲသုံးလို့ရပါတယ်။ nrc_card က တယောက်ကို တခုပဲ ဖြစ်တဲ့ အတွက်

db.person.createIndex({ nrc_card: 1 },{ sparse: true, unique: true })

Unique ကတော့ ရှင်းပါတယ် documents တွေမှာ ထပ်တဲ့ data ပါလို့မရတာပါပဲ။
အကယ်လို့ query တွေက field တခုထက် ပိုတဲ့ အရာတွေ ရှိတယ်ဆိုပါစို့။ အသက် ၂၀ အောက် အမျိုးသမီးတွေ ရှာချင်တယ်ဆိုပါတော့။ Mongodb မှာ Compound indexes ဆိုတာရှိပါတယ်။

db.person.createIndex( { "age": 1, "gender": 1 } )        

အဲ့လိုဆိုရင် age နဲ့ gender ကို တွဲပီး index လုပ်ပေးပါတယ်။ Query မှာ gender မပါခဲ့ရင်လဲ age တခုတည်း index လုပ်ထားသလို support ပေးပါတယ်။ သတိထားရမှာက compound index က ကိုယ့် index ထားတဲ့ ပုံစံ အတိုင်းပဲ query လုပ်လို့ရမှာပါ။ ဆိုလိုတာက အသက် ၂၀ အောက် အမျိုးသမီးဆိုရင် အလုပ်လုပ်ပေမယ့် အမျိုးသမီး အသက် ၂၀ အောက်ဆိုရင် အလုပ်မလုပ်ပါဘူး။ အရင်ဆုံး index ထားတဲ့ field က အရင် လာ ရမှာပါ။
တခါတလေ data တွေ တော်တော်များများထည့်ပြီးမှ index လုပ်ရမယ့် field ပေါ်လာခဲ့ ရင်တော့ background မှာ လုပ်လို့ရပါတယ်။

db.person.createIndex({ dob: 1 },{ background: true })

Mongodb index လုပ်တဲ့ နေရာမှာ အများဆုံး ကျွန်တော် သုံးဖြစ်တာတွေပါ။ ဒီထက်ပိုပီးလိုအပ်တာတွေ လုပ်ချင်တာတွေ သိချင်တာတွေရှိရင်တော့ ဒီမှာ ကြည့်နိုင်ပါတယ်။

Database မှာ index တွေထည့်ပီးပီဆိုပေမယ့် code အပိုင်းမှာလဲ သတိထားရမှာတွေရှိပါတယ်။ မလိုအပ်ပဲ query တွေ ခဏခဏ မလုပ်ဖို့။ ဖြစ်နိုင်ရင် mongodb ရဲ့ methods တွေကို တိုက်ရိုက်ယူသုံးဖို့ တိုက်တွန်းချင်ပါတယ်။ အဲ့ဒါဆိုရင်တော့ read performance အနည်းနဲ့ အများတော့ တက်လာမှာပါ။

Data Size Checking

Mongodb ရဲ့ data တွေများလာတော့ server မှာ disk space ပြည့်မလို ဖြစ်ဖူးတယ်။ အဲ့ဒါနဲ့ ဘယ် collection  တွေက များနေတာလဲ ဆိုတာ လိုက်ရှာရတာပေါ့။ Mongodb မှာက db.collection.stats() ဆိုတဲ့ method ရှိတယ်။ ဒါပေမယ့် တခုခြင်းဆီကို လိုက်ကြည့်နေရင် ကြာနေတယ်ဆိုပီး Google ခေါက်လိုက်တော့ ကိုယ်လိုချင်တဲ့ script တခုတွေတယ်။


 var collectionNames = db.getCollectionNames(), stats = [];
 collectionNames.forEach(function (n) { 
   stats.push(db[n].stats()); });
   stats = stats.sort(function(a, b) { return b['size'] - a['size']; });
   for (var c in stats) { 
      print(stats[c]['ns'] + ": " + stats[c]['size'] + " (" + stats[c]['storageSize'] + ")"); 
    }

အဲ့ script ကို mongo shell မှာ သိချင်တဲ့ db ထဲဝင်ပီး run လိုက်ရင် ကိုယ်သိချင်တဲ့  ဘယ် collection က များနေလဲဆိုတာသိရပါပီ။ အဲ့တော့မှ export ထုတ်သင့်တန် ထုတ်၊ Delete သင့်တန် Delete၊ compact လုပ်သင့်တန်လုပ်ပေါ့။

Reclaiming Disk Space

ကိုယ်က data တွေ Delete လိုက်ပေမယ့် database ထဲမှာ index တွေ delete လုပ်တဲ့ data တွေအတွက် ချန်ထားတဲ့ space တွေရှိသေးတယ်။ အဲ့ဒါတွေကို reclaim ပြန်လုပ်ဖို့အတွက် compact လုပ်ပေးရပါတယ်။

db.runCommand({compact:'collectionName'})

Compact မလုပ်ခင်တခု သတိထားရမှာက database level command ဖြစ်တဲ့ အတွက် ကျန်တဲ့ operations တွေကို block လုပ်ပစ်မှာ ဖြစ်ပါတယ်။ အဲ့ဒါကြောင့် compact မလုပ်ခင်တော့ server  down ထားရင် အဆင်ပြေမှာပါ။

ဆက်ရေးရင်တော့ ကျန်သေးပေမယ့် ဒီမှာပဲ အပိုင်းတစ် ဆိုပီး အဆုံးသတ်လိုက်ပါတော့မယ်။ အစက နည်းပညာနဲ့ ပတ်သက်ပီး ရေးဖို့ စိတ်ကူး  မရှိသေးပေမယ့် app တွေကို production တင်ရင် ခဏခဏ ပြသနာတက်နေတဲ့ junior လေးတွေ အဆင်ပြေပါစေတော့ လို့ စိတ်ကူးနဲ့ ရေးလိုက်တာပါ။