সংস্করণ 3.2 থেকে শুরু করে, MongoDB প্রতিটি সূচকের ব্যবহারের পরিসংখ্যান ট্র্যাক করে। এই পরিসংখ্যানগুলি অ্যাক্সেস করতে, MongoDB $indexStats একত্রিতকরণ পাইপলাইন পর্যায় অফার করে। MongoDB-তে অব্যবহৃত সূচী খোঁজার সময় এখানে ছয়টি বিবেচনা রয়েছে।
উদাহরণস্বরূপ, নিম্নলিখিত কমান্ডটি "test.foo" সংগ্রহের জন্য সূচক পরিসংখ্যান প্রদান করবে:
db.foo.aggregate( [ { $indexStats: { } } ] )
https://bit.ly/2seXnzo
আমরা $indexStats আউটপুট বর্ণনা করব না কারণ এখানে প্রচুর ডকুমেন্টেশন এবং অনেক ভাল নিবন্ধ রয়েছে যা এই বিষয়টিকে কভার করে। পরিবর্তে, $indexStats অপারেটর ব্যবহার করার সময় আমরা বিভিন্ন ক্ষেত্রে ছয়টি বিবেচনা সরবরাহ করব।
বিবেচনা 1:প্রতিটি পরিষেবা পুনরায় চালু হলে পরিসংখ্যান পুনরায় সেট করা হয়
$indexStats অপারেটর ব্যবহার করার সময় সর্বদা "accesses.since" ক্ষেত্রে অতিরিক্ত মনোযোগ দিন। কিছু ক্যোয়ারী প্যাটার্ন বিরল হতে পারে, যেমন দিনের ব্যাচ প্রক্রিয়ার শেষ বা একটি সাপ্তাহিক প্রতিবেদন, তাই নিশ্চিত করুন যে পরিসংখ্যানের সময়কাল আপনি মূল্যায়ন করতে যাচ্ছেন তা আপনার প্রয়োজনগুলিকে কভার করে৷ নিম্নলিখিত স্ক্রিপ্টটি আপনাকে একটি থ্রেশহোল্ড সেট করতে দেয় (ঘণ্টায়) এবং একটি অব্যবহৃত সূচক মেনে না হলে একটি সতর্কতা প্রিন্ট করবে।
threshold_hours=24; db.foo.aggregate( [ { $indexStats: { } } ] ).forEach(function(f){if (f.accesses.ops==0) {if (ISODate()-f.accesses.since < threshold_hours*3600*1000) {print('Index: ' +f.name+ ' accessed: ' +f.accesses.ops+ ' times, Status:WARNING, The duration of statistics DOES NOT meet your compliance')} else {print('Index: ' +f.name+ ' accessed: ' +f.accesses.ops+ ' times, Status:OK The duration of statistics meet your compliance');};}})
আপনার জন্য সঠিক থ্রেশহোল্ড কি? কোন সহজ উত্তর নেই। সমস্ত স্টেটমেন্ট প্যাটার্ন একই ফ্রিকোয়েন্সি সহ কার্যকর করা হয় না, তাই সঠিক প্রান্তিকটি অ্যাপ্লিকেশন থেকে অ্যাপ্লিকেশনে পরিবর্তিত হয় এবং একই ডাটাবেসের মধ্যে সংগ্রহ প্রতি আলাদাও হতে পারে।
বিবেচনা 2:মাধ্যমিক পড়া
ডিফল্টরূপে, $indexStats প্রাথমিক থেকে পড়ে। যদি আপনার আবেদন শুধুমাত্র সেকেন্ডারি থেকে পড়ে, তাহলে প্রাথমিকের বিপরীতে $indexStats চালালে ভুল সিদ্ধান্তে পৌঁছাবে। মাধ্যমিক থেকে ফলাফল পড়ার জন্য, আপনি উপরের প্রথম বিবেচনা থেকে স্ক্রিপ্ট ব্যবহার করতে পারেন, কিন্তু db.getMongo().setReadPref(‘secondary’) চালান। এটি চালানোর আগে, যা সেকেন্ডারি থেকে কমান্ড পড়তে বাধ্য করে।
এখন প্রশ্ন হল "যদি একটি সংগ্রহ প্রাথমিক এবং মাধ্যমিক উভয়ই পঠিত হয়?" নিম্নলিখিত স্ক্রিপ্টটি ব্যবহার করে, আপনি প্রাথমিক এবং মাধ্যমিক উভয় ক্ষেত্রেই অব্যবহৃত সূচীগুলির সাথে idx অ্যারে তৈরি করতে পারেন:
idx=[]; db.foo.getIndexes().forEach(function(f){idx.push(f.name)}) db.getMongo().setReadPref('primary'); db.foo.aggregate( [ { $indexStats: { } } ] ).forEach(function(f){if (f.accesses.ops>0) { var index = idx.indexOf(f.name); if (index > -1) {idx.splice(index, 1);};}}) db.getMongo().setReadPref('secondary'); db.foo.aggregate( [ { $indexStats: { } } ] ).forEach(function(f){if (f.accesses.ops>0) { var index = idx.indexOf(f.name); if (index > -1) {idx.splice(index, 1);};}})
আইডিএক্স অ্যারের বিষয়বস্তুতে প্রাথমিক এবং মাধ্যমিক উভয় ক্ষেত্রেই অব্যবহৃত সূচক থাকবে। কমপ্লায়েন্স উইন্ডো (থ্রেশহোল্ড_ঘন্টা) সম্পর্কে কী? বিবেচনা 1 (পূর্ববর্তী উপধারা) থেকে স্ক্রিপ্টটি সামান্য পরিবর্তন করা আমাদের সময় সম্মতি প্রয়োগ করার অনুমতি দেবে। শুধু নিচে দেওয়া একটি দিয়ে অ্যাগ্রিগেশন অংশটি প্রতিস্থাপন করুন এবং setReadPref ব্যবহার করে প্রাইমারি এবং সেকেন্ডারির বিপরীতে স্ক্রিপ্টটি চালান:
db.foo.aggregate( [ { $indexStats: { } } ,{$match:{"name" : {$in:idx}}}] ).
যদি প্রাথমিক এবং মাধ্যমিকগুলি বিভিন্ন সম্মতির ফলাফল দেয়, তবে সর্বোত্তম পদ্ধতি হল উভয় স্তর মেনে চলার জন্য অপেক্ষা করা।
সেকেন্ডারি রিড প্রেফারেন্স ব্যবহার করলে "ভুল ফলাফল" হতে পারে যে ক্ষেত্রে একটি মাধ্যমিক সম্প্রতি রিস্টার্ট হয়েছে এবং স্ক্রিপ্ট পরিসংখ্যান টানতে সেকেন্ডারি বেছে নেয়। এই ক্ষেত্রে, একটি ভাল পদ্ধতি হল db.serverStatus().uptime চেক করা এবং উচ্চ আপটাইম সহ মাধ্যমিক বাছাই করুন। আপটাইম পদ্ধতির জন্য স্ক্রিপ্টে একটি ভিন্ন পদ্ধতির প্রয়োজন যা এই ব্লগ পোস্টের ভবিষ্যতের সংশোধনে প্রয়োগ করা হবে৷
বিবেচনা 3:রেপ্লিকা সেট ট্যাগ
রেপ্লিকা সেট ট্যাগগুলি অনেক ব্যবহারের ক্ষেত্রে প্রযোজ্য তবে এটি প্রধানত একটি ভূ-প্রতিলিপি দৃশ্যকল্পে পঠিত স্থানের জন্য এবং ডেডিকেটেড নোডগুলিতে নির্দিষ্ট কাজের চাপকে লক্ষ্য করার জন্য ব্যবহৃত হয় (যেমন, ভারী বিশ্লেষণমূলক ক্রিয়াকলাপ)। ওয়ার্কলোড টার্গেটিংয়ের ক্ষেত্রে, ট্যাগ করা নোডগুলিকে অবশ্যই আলাদাভাবে পরীক্ষা করা উচিত কারণ তারা একটি সূচক বা সূচী ব্যবহার করতে পারে যা অন্য নোডগুলি ব্যবহার করে না। এটি জিও-প্রতিলিপির ক্ষেত্রেও হতে পারে, যদিও এটি আরও বিরল। বিবেচনা 1 থেকে স্ক্রিপ্টটি স্ক্রিপ্টের একেবারে শুরুতে রিডপ্রেফারেন্স যোগ করার সাথে একটি ট্যাগ করা সদস্য পরীক্ষা করতে ব্যবহার করা যেতে পারে। বিশ্লেষণের জন্য চিহ্নিত একটি সেকেন্ডারিতে পড়ার পছন্দ সেট করার জন্য এখানে একটি উদাহরণ রয়েছে:
db.getMongo().setReadPref('secondary', [ { "workload": "analytics" } ] ) .
উপরের দ্বিতীয় বিবেচনার শেষ অনুচ্ছেদে বর্ণিত ভবিষ্যত পদ্ধতি, ট্যাগ করা সেকেন্ডারি চেক করার জন্যও প্রসারিত করা যেতে পারে।
বিবেচনা 4:TTL সূচকগুলি
TTL সূচীগুলি ক্রিয়াকলাপ পরিবেশন করে তবে তাদের প্রধান ব্যবহার ডেটা ছাঁটাইয়ের জন্য। $indexStats-এর পক্ষে এই সূচীগুলিকে অব্যবহৃত হিসাবে রিপোর্ট করার খুব সম্ভাবনা কারণ TTL মনিটর একটি সূচক অপারেশন হিসাবে গণনা করে না। আপনি অবশ্যই $indexStats রিপোর্টের ফলাফলের উপর ভিত্তি করে একটি TTL সূচক বাদ দিতে চান না তাই স্ক্রিপ্টগুলিকে অবশ্যই এই ধরনের সূচক বাদ দিতে হবে।
দ্বিতীয় বিভাগ থেকে পপুলেট আইডিএক্স অ্যারে স্ক্রিপ্টে একটি ছোট পরিবর্তন কাজটি করবে। দ্বিতীয় লাইনটি নিম্নলিখিত একটি দিয়ে প্রতিস্থাপন করুন এবং idx অ্যারেতে কোনো TTL সূচক থাকবে না।
db.foo.getIndexes().forEach(function(f){if (f.expireAfterSeconds==undefined) {idx.push(f.name)}})
বাদ দেওয়া সূচীগুলির বিষয়ে আলোচনাকে আরও এক ধাপ এগিয়ে নিয়ে গিয়ে, আমরা দাবি করতে পারি যে _idও এই বিভাগে পড়ে৷ স্পষ্টতই, আপনি অব্যবহৃত হলেও _id সূচক ড্রপ করতে পারবেন না। একটি সংগ্রহ যা কখনোই _id সূচককে স্পর্শ করে না তার পুনরায় ডিজাইনের প্রয়োজন হতে পারে।
বিবেচনা 5:শার্ডেড ক্লাস্টার
যখন শার্ড ক্লাস্টারের কথা আসে, তখন $indexStats-এর আউটপুট মূল্যায়ন করার আগে দুটি আইটেম বিবেচনা করতে হয়। প্রথমত, শার্ড সংগ্রহের বিপরীতে $indexStats ব্যবহার করার সময়, শার্ড কী সূচকটি অব্যবহৃত হিসাবে শ্রেণীবদ্ধ করা সম্ভব। উদাহরণস্বরূপ, {_id:”hashed”}-এ শার্ড করা একটি লেখা-ভারী সংগ্রহ (এমনকি লেখার বিতরণের জন্য) কিন্তু কোনো রিড/আপডেট/ডিলিট অপারেশন ছাড়াই যা _id সূচক ব্যবহার করতে পারে। এই ক্ষেত্রে, {_id:”hashed”}৷ অব্যবহৃত হিসাবে রিপোর্ট. সূচকটি বাদ দেওয়া ভাল ধারণা নয় কারণ এটি আপনার শার্ড ক্লাস্টারকে ভেঙে ফেলতে চলেছে। আপনি যদি 'stats.foo' সংগ্রহের জন্য শার্ড কী বাদ দিতে চান, তাহলে নিম্নলিখিত স্ক্রিপ্টটি বিবেচনা দুটিতে বর্ণিত পদ্ধতির সাথে সংযুক্ত করা যেতে পারে (সেকেন্ডারি রিড) এবং শার্ড কীটি idx অ্যারে থেকে বাদ দেওয়া হবে।
shardkey=db.getSiblingDB('config').collections.findOne({_id:'stats.foo'},{_id:0,key:1}); db.foo.getIndexes().forEach(function(f){if (JSON.stringify(f.key)!=JSON.stringify(shardkey.key)) {printjson(shardkey.key);printjson(f.key);idx.push(f.name)}})
আরেকটি বিবেচনা $indexStats-এর আউটপুটের সাথে সম্পর্কিত, কারণ এটি এখন সংগ্রহে উপস্থিতি থাকা প্রতিটি শর্ড থেকে পরিসংখ্যান প্রদান করে। যদিও এটি অস্বাভাবিক, এমন কিছু ঘটনা রয়েছে যে একটি সূচক(গুলি) কয়েকটি শার্ডে অব্যবহৃত হিসাবে রিপোর্ট করে যখন অন্যান্য শার্ডগুলি এটি ব্যবহার করে। একটি দুর্বল শার্ড কী কারণ হতে পারে তবে সবচেয়ে সাধারণ দৃশ্যের নাম "কভারিং ইনডেক্স"।
কভারিং সূচীগুলিকে আরও ভালভাবে বোঝার জন্য এখানে একটি উদাহরণ দেওয়া হল:সূচী {a:1} এবং {a:1,b:1} উভয়ই 'a' ক্ষেত্রে একটি সমতা ম্যাচ পরিবেশন করতে পারে। যদি shardA-এর অপ্টিমাইজার বাছাই করে {a:1} এবং shardB-এর পিকগুলি {a:1,b:1}, উভয় সূচী অন্তত একটি শার্ডের জন্য অব্যবহৃত রিপোর্ট করবে।
চ্যালেঞ্জ হল কোন সূচকগুলি বিশ্বব্যাপী ব্যবহৃত হয় না তা খুঁজে বের করা। বিবেচনা 2 স্ক্রিপ্ট (সেকেন্ডারি রিডস) এর একত্রিত অংশ (একটি forEach লুপ দ্বারা অনুসরণ করে) প্রতিস্থাপন করা নিম্নলিখিত একটি দিয়ে কাজ করবে:
db.foo.aggregate( [ { $indexStats: { } } , {$group: {_id:"$name",number : {$sum:"$accesses.ops"}}}] ).forEach(function(f){if (f.number>0) { var index = idx.indexOf(f._id); if (index > -1) {idx.splice(index, 1);};}})
আরেকটি চ্যালেঞ্জ হল আংশিকভাবে ব্যবহৃত সূচকগুলি আবিষ্কার করা। অপ্রয়োজনীয় সূচক বা সূচক সনাক্তকরণের ত্রুটির ক্ষেত্রে এই তথ্যটি সহায়ক হতে পারে। আইডিএক্স অ্যারে ব্যবহার করে, নিম্নোক্ত সমষ্টি/স্ক্রিপ্ট বিশ্বব্যাপী অব্যবহৃত সূচী দ্বারা পপুলেট করা হয় এবং আংশিকভাবে-ব্যবহারের সূচীগুলি রিপোর্ট করে:
db.foo.aggregate( [ { $indexStats: { } },{$match:{name:{$nin:idx},"accesses.ops":0}}]).forEach(function(f){print("Index "+f.name+" reports as partially unused on shard/host " +f.host)})
বিবেচনা 6:সর্বনিম্ন ব্যবহৃত সূচকগুলি
অব্যবহৃত সূচীগুলি আবিষ্কার করা এবং বাদ দেওয়া অত্যন্ত গুরুত্বপূর্ণ তবে সর্বনিম্ন ব্যবহৃত সূচকগুলি মূল্যায়ন করাও গুরুত্বপূর্ণ। যদি একটি সূচক সপ্তাহে বা মাসের মধ্যে মাত্র এক বা দুইবার অ্যাক্সেস করা হয় তবে এর অর্থ হতে পারে যে এটি আপনার কাজের চাপের জন্য প্রয়োজনীয় বা উপকারী নয়। নিম্নোক্ত সমষ্টি ব্যবহার করে পর্যায়ক্রমে কম-ব্যবহৃত সূচকগুলি পরীক্ষা করা সর্বদা একটি ভাল অভ্যাস:
db.foo.aggregate( [ { $indexStats: { } },{$match:{"accesses.ops":{$gt:0}}},{$group: {_id:"$name",number : {$sum:"$accesses.ops"}}},{$sort:{number:1}}] )
তারপরে, উপযুক্ত পদক্ষেপগুলি গ্রহণ করুন যা হয় সূচক(গুলি) বাদ দিতে, সূচক(গুলি) সংজ্ঞা পরিবর্তন করতে পারে, অথবা এমনকি সূচক(গুলি) অপ্রয়োজনীয় করতে আপনার স্কিমা/অ্যাপ্লিকেশন লজিক পরিবর্তন করতে পারে৷
আমরা আপনার জন্য এখানে আছি
আপনার MongoDB দৃষ্টান্তগুলির জন্য আপনার সূচীগুলি পরিষ্কার করতে আমরা আপনাকে সাহায্য করতে এখানে আছি। আপনাকে যা করতে হবে তা হল [email protected]এ একটি টিকিট তৈরি করুন এবং আপনার সূচী উন্নত করতে আমাদের সাহায্য করুন!