ধীরগতির কোয়েরির সমস্যা সমাধান করতে, কোয়েরি এক্সপ্লেইন (Query Explain) ব্যবহার করে কোয়েরি এক্সিকিউশন প্ল্যান এবং রানটাইম এক্সিকিউশন প্রোফাইল সংগ্রহ করুন। এক্সিকিউশন প্রোফাইলের উপর নির্ভর করে কোয়েরির পারফরম্যান্স অপ্টিমাইজ করার জন্য আপনি যে পদক্ষেপগুলো নিতে পারেন, তা নিম্নলিখিত বিভাগে বর্ণনা করা হয়েছে:
ফলাফলের সংখ্যা সীমিত করুন
কোয়েরিটি অনেকগুলো ডকুমেন্ট ফেরত দিচ্ছে কিনা তা শনাক্ত করতে এক্সিকিউশন ট্রি-তে থাকা 'records returned' ফিল্ডটি ব্যবহার করুন। limit(...) স্টেজটি ব্যবহার করে ফেরত আসা ডকুমেন্টের সংখ্যা সীমিত করার কথা বিবেচনা করুন। এটি নেটওয়ার্কের মাধ্যমে ক্লায়েন্টদের কাছে ফলাফল ফেরত পাঠানোর সময় সেগুলোর সিরিয়ালাইজড বাইট সাইজ কমিয়ে দেয়। যেসব ক্ষেত্রে ` Limit নোডের আগে একটি MajorSort নোড থাকে, সেখানে কোয়েরি ইঞ্জিন ` Limit এবং MajorSort নোড দুটিকে একত্রিত করতে পারে এবং একটি সম্পূর্ণ ইন-মেমরি ম্যাটেরিয়ালাইজেশন ও সর্টের পরিবর্তে একটি `TopN` সর্ট ব্যবহার করে, যা কোয়েরিটির জন্য প্রয়োজনীয় মেমরি কমিয়ে দেয়।
ফলাফল ডকুমেন্টের আকার সীমিত করুন
select(...) ব্যবহার করে শুধুমাত্র প্রয়োজনীয় ফিল্ডগুলো ফেরত দিয়ে অথবা remove_fields(...) ব্যবহার করে অতিরিক্ত বড় ফিল্ডগুলো বাদ দিয়ে ফেরত আসা ডকুমেন্টের আকার সীমিত করার কথা বিবেচনা করুন। এটি অন্তর্বর্তী ফলাফল প্রক্রিয়াকরণের কম্পিউট ও মেমরি খরচ কমাতে এবং নেটওয়ার্কের মাধ্যমে ক্লায়েন্টদের কাছে ফেরত পাঠানোর সময় ফলাফলের সিরিয়ালাইজড বাইট সাইজ কমাতে সাহায্য করে। যেসব ক্ষেত্রে কোয়েরিতে উল্লেখিত সমস্ত ফিল্ড একটি সাধারণ ইনডেক্সের আওতায় থাকে, সেখানে এটি কোয়েরিটিকে ইনডেক্স স্ক্যানের মাধ্যমে সম্পূর্ণরূপে কভার করার সুযোগ দেয়, ফলে প্রাইমারি স্টোরেজ থেকে ডকুমেন্ট আনার প্রয়োজন হয় না।
সূচক ব্যবহার করুন
ইনডেক্সগুলো সেট আপ ও অপ্টিমাইজ করতে নিম্নলিখিত নির্দেশাবলী ব্যবহার করুন।
কোয়েরিটি ইনডেক্স ব্যবহার করছে কিনা তা শনাক্ত করুন।
এক্সিকিউশন ট্রি-এর লিফ নোডগুলো পরীক্ষা করে আপনি শনাক্ত করতে পারেন যে কোয়েরিটি কোনো ইনডেক্স ব্যবহার করছে কিনা। যদি এক্সিকিউশন ট্রি-এর লিফ নোডটি একটি TableScan নোড হয়, তার মানে হলো কোয়েরিটি কোনো ইনডেক্স ব্যবহার করছে না এবং প্রাইমারি স্টোরেজ থেকে ডকুমেন্ট স্ক্যান করছে। যদি কোনো ইনডেক্স ব্যবহার করা হয়, তাহলে এক্সিকিউশন ট্রি-এর লিফ নোডটিতে ইনডেক্স আইডি এবং ইনডেক্সের ফিল্ডগুলো প্রদর্শিত হবে।
আরও ভালো সূচক শনাক্ত করুন
একটি ইনডেক্স কোনো কোয়েরির জন্য তখনই কার্যকর হয়, যখন এটি প্রাইমারি স্টোরেজ থেকে কোয়েরি ইঞ্জিনকে প্রয়োজনীয় ডকুমেন্টের সংখ্যা কমাতে পারে অথবা এর ফিল্ডের ক্রমবিন্যাস কোয়েরিটির সর্ট (Sort) সংক্রান্ত চাহিদা পূরণ করতে পারে।
যদি কোনো কোয়েরির জন্য একটি ইনডেক্স ব্যবহার করা হয়, কিন্তু কোয়েরি ইঞ্জিন তারপরেও অনেক ডকুমেন্ট ফেচ করে এবং বাদ দিয়ে দেয়—যা একটি স্ক্যান নোডের মাধ্যমে অনেক রেকর্ড রিটার্ন করার পর একটি ফিল্টার নোডের মাধ্যমে অল্প কিছু রেকর্ড রিটার্ন করার মাধ্যমে বোঝা যায়—তবে এটি একটি লক্ষণ যে ইনডেক্স ব্যবহার করে পূরণ করা কোয়েরি প্রেডিকেটটি সিলেক্টিভ নয়। আরও উপযুক্ত ইনডেক্স তৈরি করতে, ‘ইনডেক্স তৈরি করুন’ দেখুন।
যদি কোনো কোয়েরির জন্য একটি ইনডেক্স ব্যবহার করা হয়, কিন্তু কোয়েরি ইঞ্জিন তারপরেও রেজাল্ট সেটের ইন-মেমরি পুনর্বিন্যাস সম্পাদন করে, যা কোয়েরি এক্সিকিউশন ট্রিতে একটি MajorSort নোড দ্বারা চিহ্নিত হয়, তবে এটি একটি লক্ষণ যে ব্যবহৃত ইনডেক্সটি কোয়েরিটির সর্ট প্রয়োজনীয়তা পূরণের জন্য ব্যবহার করা যাবে না। আরও উপযুক্ত একটি ইনডেক্স তৈরি করতে, পরবর্তী বিভাগটি দেখুন।
ইনডেক্স তৈরি করুন
ইনডেক্স তৈরি করতে ইনডেক্স ম্যানেজমেন্ট ডকুমেন্টেশন অনুসরণ করুন। আপনার কোয়েরি যাতে ইনডেক্স ব্যবহার করতে পারে, তা নিশ্চিত করতে নিম্নলিখিত ক্রমে ফিল্ড সহ সাধারণ (মাল্টি-কি নয়) ইনডেক্স তৈরি করুন:
- যেসব ফিল্ড ইকুয়ালিটি অপারেটরে ব্যবহৃত হবে। বিভিন্ন কোয়েরিতে পুনঃব্যবহারের সম্ভাবনা সর্বাধিক করার জন্য, কোয়েরিগুলোর মধ্যে ইকুয়ালিটি অপারেটরে ফিল্ডগুলোর উপস্থিতির ক্রমহ্রাসমান অনুসারে সাজান।
- যেসব ফিল্ডের উপর ভিত্তি করে সর্টিং করা হবে (একই ক্রমে)।
- কোয়েরি কনস্ট্রেইন্ট সিলেক্টিভিটির অবরোহী ক্রম অনুসারে রেঞ্জ বা ইনইকুয়ালিটি অপারেটরে ব্যবহৃত ফিল্ডসমূহ।
- ইনডেক্সে কোয়েরির অংশ হিসেবে যে ফিল্ডগুলো ফেরত আসবে: ইনডেক্সে এই ধরনের ফিল্ড অন্তর্ভুক্ত করলে তা কোয়েরিটি সম্পন্ন করতে পারে এবং প্রাইমারি স্টোরেজ থেকে ডকুমেন্ট ফেচ করার প্রয়োজন এড়ানো যায়।
ইনডেক্স বা টেবিল স্ক্যান করতে বাধ্য করুন
আপনি যখন Cloud Firestore কোয়েরি করেন, তখন এটি স্বয়ংক্রিয়ভাবে এমন ইনডেক্সগুলো ব্যবহার করে যা কোয়েরিটিকে আরও কার্যকর করে তুলতে পারে। ফলে, আপনার কোয়েরিগুলোর জন্য কোনো ইনডেক্স নির্দিষ্ট করার প্রয়োজন নেই। তবে, আপনার ওয়ার্কলোডের জন্য গুরুত্বপূর্ণ কোয়েরিগুলোর ক্ষেত্রে, আরও ধারাবাহিক পারফরম্যান্সের জন্য আমরা আপনাকে forceIndex অপশনটি ব্যবহার করার পরামর্শ দিই।
কিছু ক্ষেত্রে, Cloud Firestore এমন একটি ইনডেক্স বেছে নিতে পারে যা কোয়েরি ল্যাটেন্সি বাড়িয়ে দেয়। যদি আপনি পারফরম্যান্স রিগ্রেশনের জন্য ট্রাবলশুটিং ধাপগুলো অনুসরণ করে থাকেন এবং নিশ্চিত হন যে কোয়েরিটির জন্য একটি ভিন্ন ইনডেক্স ব্যবহার করা যুক্তিযুক্ত, তাহলে আপনি forceIndex অপশনটি ব্যবহার করে ইনডেক্সটি নির্দিষ্ট করে দিতে পারেন।
আপনি পাইপলাইন অপারেশনের যেকোনো ইনপুট স্টেজে forceIndex অপশনটি ব্যবহার করে Cloud Firestore ডিফল্ট কোয়েরি প্ল্যানকে ওভাররাইড করতে এবং ব্যবহারের জন্য একটি ইনডেক্স নির্দিষ্ট করে দিতে পারেন, অথবা একটি টেবিল স্ক্যান জোরপূর্বক চালু করতে পারেন।
একটি নির্দিষ্ট সূচক জোর করে
কোয়েরিকে একটি নির্দিষ্ট ইনডেক্স ব্যবহারে বাধ্য করতে, ` forceIndex অপশনে ইনডেক্স আইডিটি একটি স্ট্রিং হিসেবে প্রদান করুন। আপনি কনসোল অথবা এরর মেসেজ থেকে ইনডেক্স আইডিটি খুঁজে নিতে পারেন।
নিম্নলিখিত উদাহরণটি প্ল্যানারকে CICAgOi36pgK আইডি সহ সূচকটি ব্যবহার করতে বাধ্য করে:
নোড.জেএস
// Force Planner to use Index ID CICAgOi36pgK await db.pipeline() .collectionGroup({ collectionId: "customers", forceIndex: "CICAgOi36pgK" }) .limit(100) .execute();
জাভা
// Force Planner to use Index ID CICAgOi36pgK Pipeline.Snapshot results1 = firestore.pipeline() .collectionGroup("customers", new CollectionGroupOptions() .withHints(new CollectionHints().withForceIndex("CICAgOi36pgK"))) .limit(100) .execute().get();
যান
// Force Planner to use Index ID CICAgOi36pgK snapshot1 := client.Pipeline(). CollectionGroup("customers", firestore.WithForceIndex("CICAgOi36pgK")). Limit(100). Execute(ctx)
একটি নির্দিষ্ট ইনডেক্স প্রয়োগ করতে বাধ্য করার কিছু ব্যবহার নিচে দেওয়া হলো:
- বিভিন্ন সূচকের কার্যকারিতা পরীক্ষা করা হচ্ছে।
- কোনো কোয়েরির জন্য একটি নির্দিষ্ট ও জ্ঞাত-সর্বোত্তম ইনডেক্স ব্যবহার নিশ্চিত করা।
- কোনো নির্দিষ্ট কোয়েরির জন্য অপটিমাইজারের ডিফল্ট পছন্দটি সর্বোত্তম না হলে, সেটিকে অগ্রাহ্য করা।
নির্দিষ্ট ইনডেক্সটি খুঁজে না পাওয়া গেলে কোয়েরিটি ব্যর্থ হয়।
টেবিল স্ক্যান করতে বাধ্য করুন
টেবিল স্ক্যান কোনো সেকেন্ডারি ইনডেক্স ব্যবহার না করেই কালেকশন বা কালেকশন গ্রুপের ডকুমেন্টগুলো পড়ে। টেবিল স্ক্যান জোরপূর্বক করতে, forceIndex primary তে সেট করুন।
নিম্নলিখিত উদাহরণটি একটি টেবিল স্ক্যান করতে বাধ্য করে:
// Force Planner to only do a Full-Table Scan
db.pipeline()
.collectionGroup({ collectionId: "customers", forceIndex: "primary" })
.limit(100)
নিম্নলিখিত ক্ষেত্রগুলিতে আপনি টেবিল স্ক্যান ব্যবহার করতে পারেন:
- খুব ছোট সংগ্রহের জন্য যেখানে ইনডেক্স ওভারহেড যুক্তিসঙ্গত নয়।
- যেসব কোয়েরি কোনো কালেকশনের অধিকাংশ ডকুমেন্ট অ্যাক্সেস করে।
- ডিবাগিং এবং পারফরম্যান্স তুলনার জন্য।
Query Explain-এর সাথে forceIndex ব্যবহার করুন
forceIndex এর প্রভাব পর্যবেক্ষণ করতে আপনি Query Explain ব্যবহার করতে পারেন, বিশেষ করে এর analyze অপশনটি সহ।
- এক্সিকিউশন ট্রি-এর লিফ নোডগুলিতে ইনডেক্স আইডি পরীক্ষা করে যাচাই করুন যে Cloud Firestore
forceIndexএ নির্দিষ্ট ইনডেক্সটি ব্যবহার করেছে কিনা। -
forceIndex: "primary"ব্যবহার করার সময় প্ল্যানে একটিTableScanনোড দেখা যাচ্ছে কিনা তা নিশ্চিত করুন। - কোয়েরির পারফরম্যান্স সূক্ষ্মভাবে সমন্বয় করার জন্য
forceIndexব্যবহার করে এবং ব্যবহার না করে ল্যাটেন্সি, স্ক্যান করা ডকুমেন্ট এবং স্ক্যান করা ইনডেক্স এন্ট্রির মতো পারফরম্যান্স মেট্রিকগুলো তুলনা করুন।
forceIndex জন্য সর্বোত্তম অনুশীলন
যদিও forceIndex কোয়েরি এক্সিকিউশনের উপর আরও বেশি নিয়ন্ত্রণ প্রদান করে, বেশিরভাগ ব্যবহারের ক্ষেত্রেই Cloud Firestore কোয়েরি অপটিমাইজার সাধারণত বেশি কার্যকর। forceIndex ব্যবহার করার সময় নিম্নলিখিত সেরা অনুশীলনগুলি বিবেচনা করুন:
-
forceIndexবিচক্ষণতার সাথে ব্যবহার করুন। ডিফল্ট কোয়েরি প্ল্যান ব্যবহার করে যদি আশানুরূপ পারফরম্যান্স না পান, তবে ইনডেক্স জোর করে প্রয়োগ করার আগে সমস্যাটি নির্ণয় করতে Query Explain ব্যবহার করুন। -
forceIndexব্যবহার করার সময়, আপনার কোয়েরিগুলোর পারফরম্যান্স ও খরচের বৈশিষ্ট্যগুলো বোঝার জন্য বাস্তবসম্মত ডেটা ভলিউম দিয়ে সেগুলো পরীক্ষা করে নিন। - প্রোডাকশন পরিবেশে বড় কালেকশনের ক্ষেত্রে
forceIndex: "primary"ব্যবহার করা থেকে বিরত থাকুন।