क्वेरी की परफ़ॉर्मेंस ऑप्टिमाइज़ करना

क्वेरी के धीमे चलने की समस्या हल करने के लिए, क्वेरी की व्याख्या करें सुविधा का इस्तेमाल करें. इससे आपको क्वेरी के एक्ज़ीक्यूशन प्लान और रनटाइम एक्ज़ीक्यूशन प्रोफ़ाइल के बारे में जानकारी मिलेगी. यहां दिए गए सेक्शन में, एक्ज़ीक्यूशन प्रोफ़ाइल के आधार पर क्वेरी की परफ़ॉर्मेंस को ऑप्टिमाइज़ करने के तरीके के बारे में बताया गया है:

नतीजों की संख्या सीमित करना

क्वेरी से कई दस्तावेज़ मिल रहे हैं या नहीं, यह जानने के लिए एक्ज़ीक्यूशन ट्री में, 'दिखाए गए रिकॉर्ड' फ़ील्ड का इस्तेमाल करें. limit(...) स्टेज का इस्तेमाल करके, क्वेरी से दिखाए जाने वाले दस्तावेज़ों की संख्या को सीमित करें. इससे, नेटवर्क पर क्लाइंट को दिखाए जाने वाले नतीजों के सीरियल किए गए बाइट का साइज़ कम हो जाता है. अगर Limit नोड से पहले MajorSort नोड आता है, तो क्वेरी इंजन Limit और MajorSort नोड को एक साथ जोड़ सकता है. साथ ही, पूरी तरह से इन-मेमोरी मटीरियलाइज़ेशन और सॉर्ट को TopN सॉर्ट से बदल सकता है. इससे क्वेरी के लिए मेमोरी की ज़रूरत कम हो जाती है.

नतीजे के तौर पर मिले दस्तावेज़ के साइज़ की सीमा तय करना

select(...) का इस्तेमाल करके, सिर्फ़ ज़रूरी फ़ील्ड दिखाने के लिए या remove_fields(...) का इस्तेमाल करके, बहुत बड़े फ़ील्ड को हटाने के लिए, क्वेरी के जवाब में मिले दस्तावेज़ के साइज़ को सीमित करें. इससे इंटरमीडिएट नतीजों को प्रोसेस करने के लिए, कंप्यूट और मेमोरी की लागत कम करने में मदद मिलती है. साथ ही, नेटवर्क पर क्लाइंट को भेजे जाने वाले नतीजों के सीरियल किए गए बाइट साइज़ को कम करने में मदद मिलती है. अगर क्वेरी में रेफ़र किए गए सभी फ़ील्ड, रेगुलर इंडेक्स में शामिल हैं, तो इससे क्वेरी को इंडेक्स स्कैन से पूरी तरह से कवर किया जा सकता है. इससे प्राइमरी स्टोरेज से दस्तावेज़ों को फ़ेच करने की ज़रूरत नहीं पड़ती.

इंडेक्स का इस्तेमाल करना

इंडेक्स सेट अप करने और उन्हें ऑप्टिमाइज़ करने के लिए, यहां दिए गए निर्देशों का पालन करें.

यह पता लगाना कि क्वेरी किसी इंडेक्स का इस्तेमाल कर रही है या नहीं

यह पता लगाया जा सकता है कि क्वेरी किसी इंडेक्स का इस्तेमाल कर रही है या नहीं. इसके लिए, एक्ज़ीक्यूशन ट्री में लीफ़ नोड देखें. अगर एक्ज़ीक्यूशन ट्री का लीफ़ नोड TableScan नोड है, तो इसका मतलब है कि क्वेरी किसी इंडेक्स का इस्तेमाल नहीं कर रही है. साथ ही, प्राइमरी स्टोरेज से दस्तावेज़ों को स्कैन कर रही है. अगर किसी इंडेक्स का इस्तेमाल किया जा रहा है, तो एक्ज़ीक्यूशन ट्री का लीफ़ नोड, इंडेक्स का इंडेक्स आईडी और इंडेक्स फ़ील्ड दिखाएगा.

बेहतर इंडेक्स की पहचान करना

कोई इंडेक्स, क्वेरी के लिए तब फ़ायदेमंद होता है, जब वह उन दस्तावेज़ों की संख्या को कम कर सकता है जिन्हें क्वेरी इंजन को प्राइमरी स्टोरेज से फ़ेच करना होता है. इसके अलावा, अगर इंडेक्स के फ़ील्ड का क्रम, क्वेरी की क्रम से लगाने की ज़रूरत को पूरा कर सकता है, तब भी इंडेक्स फ़ायदेमंद होता है.

अगर किसी क्वेरी के लिए इंडेक्स का इस्तेमाल किया जाता है, लेकिन क्वेरी इंजन अब भी कई दस्तावेज़ों को फ़ेच और खारिज कर रहा है, तो यह इस बात का संकेत है कि इंडेक्स का इस्तेमाल करके क्वेरी प्रेडिकेट को पूरा नहीं किया जा रहा है. इसकी पहचान, स्कैन नोड से की जाती है. यह नोड कई रिकॉर्ड दिखाता है. इसके बाद, फ़िल्टर नोड कुछ रिकॉर्ड दिखाता है. ज़्यादा सही इंडेक्स बनाने के लिए, इंडेक्स बनाना लेख पढ़ें.

अगर किसी क्वेरी के लिए इंडेक्स का इस्तेमाल किया जाता है, लेकिन क्वेरी इंजन अब भी नतीजे के सेट को मेमोरी में फिर से क्रम में लगा रहा है, जैसा कि क्वेरी एक्ज़ीक्यूशन ट्री में MajorSort नोड से पता चलता है, तो यह इस बात का संकेत है कि इस्तेमाल किए गए इंडेक्स का इस्तेमाल, क्वेरी की क्रम से लगाने की ज़रूरत को पूरा करने के लिए नहीं किया जा सकता. ज़्यादा सही इंडेक्स बनाने के लिए, अगला सेक्शन देखें.

इंडेक्स बनाना

इंडेक्स बनाने के लिए, इंडेक्स मैनेजमेंट से जुड़े दस्तावेज़ पढ़ें. यह पक्का करने के लिए कि आपकी क्वेरी इंडेक्स का इस्तेमाल कर सकती है, रेगुलर (मल्टीकी नहीं) इंडेक्स बनाएं. साथ ही, फ़ील्ड को इस क्रम में रखें:

  1. क्वेरी में इस्तेमाल किए जाने वाले सभी फ़ील्ड, समानता ऑपरेटर के साथ इस्तेमाल किए जाने चाहिए. क्वेरी में फ़ील्ड के फिर से इस्तेमाल किए जाने की संभावना को बढ़ाने के लिए, समानता ऑपरेटर के साथ इस्तेमाल किए जाने वाले फ़ील्ड को क्वेरी में उनके दिखने की संख्या के हिसाब से घटते क्रम में लगाएं.
  2. वे सभी फ़ील्ड जिनके आधार पर डेटा को क्रम से लगाया जाएगा (उसी क्रम में).
  3. ऐसे फ़ील्ड जिनका इस्तेमाल रेंज या असमानता वाले ऑपरेटर में किया जाएगा. इन्हें क्वेरी की शर्त के हिसाब से घटते क्रम में रखा जाएगा.
  4. ऐसे फ़ील्ड जिन्हें इंडेक्स में क्वेरी के हिस्से के तौर पर दिखाया जाएगा: इन फ़ील्ड को इंडेक्स में शामिल करने से, इंडेक्स क्वेरी को कवर कर पाता है. साथ ही, इसे प्राइमरी स्टोरेज से दस्तावेज़ फ़ेच करने की ज़रूरत नहीं पड़ती.

किसी इंडेक्स या टेबल को स्कैन करने के लिए मजबूर करना

Cloud Firestore से क्वेरी करने पर, यह अपने-आप उन इंडेक्स का इस्तेमाल करता है जिनसे क्वेरी को ज़्यादा असरदार बनाया जा सकता है. इसलिए, आपको अपनी क्वेरी के लिए इंडेक्स तय करने की ज़रूरत नहीं है. हालांकि, अगर आपकी क्वेरी आपके वर्कलोड के लिए ज़रूरी है, तो हमारा सुझाव है कि आप forceIndex विकल्प का इस्तेमाल करें, ताकि आपको बेहतर परफ़ॉर्मेंस मिल सके.

कुछ मामलों में, Cloud Firestore ऐसा इंडेक्स चुन सकता है जिसकी वजह से क्वेरी में लगने वाला समय बढ़ जाता है. अगर आपने परफ़ॉर्मेंस में गिरावट से जुड़ी समस्या हल करने के तरीके अपना लिए हैं और आपको लगता है कि क्वेरी के लिए किसी दूसरे इंडेक्स का इस्तेमाल करना सही रहेगा, तो forceIndex विकल्प का इस्तेमाल करके इंडेक्स तय किया जा सकता है.

पाइपलाइन ऑपरेशन में किसी भी इनपुट स्टेज पर forceIndex विकल्प का इस्तेमाल करके, Cloud Firestore के डिफ़ॉल्ट क्वेरी प्लान को बदला जा सकता है. साथ ही, इस्तेमाल करने के लिए इंडेक्स तय किया जा सकता है या टेबल स्कैन को लागू किया जा सकता है.

किसी इंडेक्स को ज़बरदस्ती लागू करना

क्वेरी को किसी खास इंडेक्स का इस्तेमाल करने के लिए मजबूर करने के लिए, forceIndex विकल्प में इंडेक्स आईडी को स्ट्रिंग के तौर पर दें. आपको कंसोल या गड़बड़ी के मैसेज से इंडेक्स आईडी मिल सकता है.

यहां दिए गए उदाहरण में, प्लानर को आईडी CICAgOi36pgK वाला इंडेक्स इस्तेमाल करने के लिए मजबूर किया गया है:

Node.js
// Force Planner to use Index ID CICAgOi36pgK
await db.pipeline()
  .collectionGroup({ collectionId: "customers", forceIndex: "CICAgOi36pgK" })
  .limit(100)
  .execute();
Java
// 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)

इन मामलों में टेबल स्कैन का इस्तेमाल किया जा सकता है:

  • बहुत छोटे कलेक्शन के लिए, जहां इंडेक्स ओवरहेड सही नहीं है.
  • उन क्वेरी के लिए जो किसी कलेक्शन में मौजूद ज़्यादातर दस्तावेज़ों को ऐक्सेस करती हैं.
  • डीबग करने और परफ़ॉर्मेंस की तुलना करने के लिए.

क्वेरी की व्याख्या करने वाली सुविधा के साथ forceIndex का इस्तेमाल करना

forceIndex के असर को देखने के लिए, क्वेरी की व्याख्या करें का इस्तेमाल explain या analyze मोड में किया जा सकता है:

  • पुष्टि करें कि Cloud Firestore ने forceIndex में बताए गए इंडेक्स का इस्तेमाल किया है. इसके लिए, इंडेक्स आईडी के लिए एक्ज़ीक्यूशन ट्री के लीफ़ नोड देखें.
  • पुष्टि करें कि forceIndex: "primary" का इस्तेमाल करते समय, प्लान में TableScan नोड दिखता हो.
  • analyze मोड की मदद से, परफ़ॉर्मेंस मेट्रिक की तुलना करें. जैसे, क्वेरी में लगने वाला समय, स्कैन किए गए दस्तावेज़, और स्कैन की गई इंडेक्स एंट्री. ऐसा forceIndex के साथ और इसके बिना, दोनों स्थितियों में करें, ताकि क्वेरी की परफ़ॉर्मेंस को बेहतर बनाया जा सके.

forceIndex के लिए सबसे सही तरीके

forceIndex से क्वेरी को लागू करने पर ज़्यादा कंट्रोल मिलता है. हालांकि, ज़्यादातर इस्तेमाल के मामलों के लिए, Cloud Firestore का क्वेरी ऑप्टिमाइज़र आम तौर पर बेहतर होता है. forceIndex का इस्तेमाल करते समय, इन सबसे सही तरीकों को ध्यान में रखें:

  • forceIndex का सोच-समझकर इस्तेमाल करें. अगर आपको डिफ़ॉल्ट क्वेरी प्लान से उम्मीद के मुताबिक परफ़ॉर्मेंस नहीं मिलती है, तो इंडेक्स को लागू करने से पहले, समस्या का पता लगाने के लिए क्वेरी की व्याख्या करें सुविधा का इस्तेमाल करें.
  • forceIndex का इस्तेमाल करते समय, पक्का करें कि आपने अपनी क्वेरी को असली डेटा के साथ टेस्ट किया हो. इससे आपको उनकी परफ़ॉर्मेंस और लागत की जानकारी मिलेगी.
  • प्रोडक्शन एनवायरमेंट में मौजूद बड़े कलेक्शन पर forceIndex: "primary" का इस्तेमाल न करें.

'क्वेरी की व्याख्या करें' सुविधा का इस्तेमाल करके क्वेरी चलाने पर मिलने वाले आउटपुट के बारे में ज़्यादा जानने के लिए, क्वेरी चलाने से जुड़ा रेफ़रंस देखें.