कोर्स
एक डेटा वैज्ञानिक होने के नाते, आपको अक्सर बहुत बड़े डेटा से निपटना होगा। भारी मात्रा में मौजूद डेटा से निपटना बिल्कुल आसान नहीं है। इसलिए, इसे यथासंभव कुशलता से संभालने के लिए, आपको यह स्पष्ट समझ होनी चाहिए कि डेटा भौतिक रूप से कैसे संगठित है ताकि आप उपयोगी तकनीकों से उसे प्रोसेस कर सकें।
SQL किसी भी आधुनिक सॉफ्टवेयर इंजीनियर के लिए आवश्यक कौशल है क्योंकि अधिकांश सॉफ्टवेयर किसी न किसी प्रकार के डेटा पर निर्भर करते हैं और RDBMS (Relational Database Management System) के साथ अच्छी तरह एकीकृत होते हैं। चाहे वह वेब एप्लिकेशन हो, कोई API हो या इन-हाउस एप्लिकेशन, RDBMS हमेशा मौजूद रहता है। और RDBMS से क्वेरी करने की भाषा SQL है।
एक डेटा वैज्ञानिक के रूप में, SQL और उससे जुड़ी तकनीकों को जानना अत्यंत महत्वपूर्ण है। जिस डेटा से आप काम कर रहे हैं, उसके बारे में आपके विशिष्ट प्रश्नों के उत्तर पाने और RDBMS पर क्वेरी चलाने के लिए SQL न्यूनतम आवश्यकता है।
DataCamp के नवीनतम वीडियो में, David Robinson (Chief Data Scientist @ DataCamp) ने दिखाया कि वह डेटा साइंस समस्या में SQL का उपयोग कैसे करते हैं। कृपया इसे देखें। उनका वर्कफ़्लो बहुत रोचक है।
आज आप इंडेक्सिंग नामक एक तकनीक के बारे में सीखेंगे जो मुख्य रूप से किसी डेटाबेस के अंदर डेटा के संगठन से संबंधित है, और आप उनमें से कुछ को SQL का उपयोग करके लागू करेंगे। यह आपको इस बात का अवलोकन देगा कि किसी डेटाबेस में जानकारी को संग्रहीत करने के लिए इंडेक्सिंग कैसे उपयोग की जा सकती है और यह तेज़ निष्पादन समय कैसे दे सकती है।
टिप्पणी: इस ट्यूटोरियल को पढ़ना शुरू करने से पहले, यह अत्यधिक अनुशंसित है कि यदि आप SQL की बुनियाद से परिचित नहीं हैं तो उन्हें सीख लें। DataCamp का Intro to SQL for Data Science कोर्स आपकी SQL की बुनियाद ताज़ा करने के लिए एक उत्कृष्ट संसाधन है।
किसी फ़ाइल में रेकॉर्ड्स के संगठन पर एक संक्षिप्त नोट
इंडेक्सिंग पर कुछ भी पढ़ना शुरू करने से पहले, यह समझना आवश्यक है कि फ़ाइलों के अंदर डेटा भौतिक रूप से कैसे संगठित होता है। स्वाभाविक रूप से, आप सभी विवरणों में नहीं जाएंगे, लेकिन संगठन का एक अच्छा अवलोकन होना इंडेक्सिंग को बहुत स्पष्ट रूप से समझने में मदद करेगा। आइए शुरू करें।
सामान्य तौर पर रेकॉर्ड्स/डेटा का संगठन इस बात से संबंधित है कि रेकॉर्ड्स कैसे संग्रहीत किए जाते हैं और इसे व्यापक रूप से दो प्रकारों में बाँटा जा सकता है:
-
आदेशित (Ordered) संगठन: किसी फ़ाइल के सभी रेकॉर्ड्स किसी सर्च की वैल्यू के अनुसार क्रमबद्ध होते हैं। किसी आदेशित फ़ाइल में भीतरी मान खोजने के लिए सामान्यतः बाइनरी सर्च का उपयोग किया जाता है। इससे खोज बहुत कुशल हो जाती है क्योंकि खोज की समय-जटिलता लॉगरिद्मिक समय में रहती है। लेकिन फ़ाइल में नए आइटम जोड़ना महंगा ऑपरेशन बन जाता है क्योंकि नए आइटम को समायोजित करने के लिए आपको पूरी फ़ाइल को पुनर्गठित करना पड़ सकता है।
-
अनादेशित (Unordered) संगठन: इस प्रकार में, रेकॉर्ड्स को फ़ाइल में जहाँ भी स्थान उपलब्ध हो, प्रायः फ़ाइल के अंत में, जोड़ दिया जाता है। इस प्रकार में रैखिक (लिनियर) खोज का उपयोग होता है, इसलिए खोज पहले वाले तरीके जितनी कुशल नहीं होती, लेकिन जोड़ना उतना महंगा ऑपरेशन नहीं होता।
हालाँकि आपके पास फ़ाइलों का आदेशित संगठन है, पर यदि फ़ाइलों के ब्लॉक आकार और फ़ाइलों के अंदर प्रत्येक रेकॉर्ड का आकार बहुत बड़ा हो तो क्या होगा? आइए अगला खंड देखते हैं।
इंडेक्सिंग की आवश्यकता
आप इस खंड की शुरुआत इस प्रेरणा को समझकर करेंगे कि फ़ाइलों/जानकारी को कुशलतापूर्वक संग्रहीत करने के लिए इंडेक्सिंग का उपयोग क्यों किया जाता है और यह इन फ़ाइलों/जानकारी से संबंधित अन्य ऑपरेशन्स को कैसे बेहतर बनाती है।
मान लीजिए आपके पास एक टेबल (रिलेशन) है जिसमें डेटाबेस में कई रेकॉर्ड्स हैं। रेकॉर्ड्स को आगे 1000 ब्लॉक्स में विभाजित किया गया है। चित्रात्मक रूप से, संगठन कुछ इस प्रकार दिखता है:

ऊपर दिए गए संगठन से स्पष्ट है कि -
- रेकॉर्ड्स के पहले कॉलम पर क्रम लागू है (मान लें यह एक रिलेशनल डेटाबेस सिस्टम है जिसमें डेटा सारणीबद्ध रूप में संगठित है)
- कुल डेटा जिन ब्लॉक्स में विभाजित है उनकी संख्या - 1000 ब्लॉक्स।
ध्यान रखें कि प्रत्येक रेकॉर्ड में अन्य कॉलम भी होते हैं, पर इस संगठन के लिए क्रम पहले कॉलम पर लागू है और ब्लॉक्स उसी अनुसार विभाजित हैं। अब, यदि आप इस संगठन या रेकॉर्ड्स के अंदर कुछ खोजने के लिए बाइनरी सर्च करते हैं, तो कुल समय होगा - $\log_{2}1000$, जो 10 समय इकाइयों के बराबर है। क्या इस खोज समय में सुधार हो सकता है?
बिल्कुल, हाँ।
इसे किताब पढ़ने के सन्दर्भ में सोचें जहाँ इंडेक्स पेज न हो। आप एक यादृच्छिक पेज खोलते हैं (या बाइनरी सर्च के मामले में किताब का बीच का पेज) और फिर वांछित पेज तक जाने के लिए पन्ने बाएँ-दाएँ पलटते हैं। इसमें निश्चित रूप से समय लगता है। है न?
लेकिन यदि किताब में इंडेक्स पेज हो, तो खोज और अधिक कुशल हो जाएगी। आप केवल इंडेक्स देखकर सीधे पेज पर जा सकते थे। ऊपर की स्थिति पर आप इसी तरह इंडेक्सिंग लागू कर सकते हैं।
यहाँ संक्षेप में देखें कि आप यहाँ इंडेक्सिंग कैसे लागू कर सकते हैं:
- पिछले संगठन में उपयोग की गई आदेशित वैल्यूज के साथ प्रत्येक ब्लॉक के लिए एक ब्लॉक पॉइंटर बनाए रखें।
इससे डेटा फ़ाइलों को संग्रहीत करने के लिए कम संख्या में ब्लॉक्स का उपयोग होगा। अब, किसी विशेष रेकॉर्ड को खोजने के लिए, आपको केवल इस नए संगठन में, जिसमें कम ब्लॉक्स हैं, खोज करनी होगी और अंततः आपको आपका रेकॉर्ड (यदि वह मौजूद है) बहुत कम समय में मिल जाएगा। आइए इसे विज़ुअलाइज़ करें। मान लेते हैं कि नए इंडेक्स किए गए रेकॉर्ड्स की संख्या 8 ब्लॉक्स में परिणत हुई, तो आपको निम्न जैसा संगठन मिलेगा:

कम ब्लॉक्स के कारण खोज समय नाटकीय रूप से कम होगा। मान लें, आप रेकॉर्ड 90 खोजना चाहते हैं। इस नए इंडेक्स्ड स्कीम में, आप पहले उसके संबंधित ब्लॉक पॉइंटर का पता लगाएंगे, जो इस मामले में 3 है, और फिर इस जानकारी का उपयोग करके आप मूल डेटा रेकॉर्ड्स को एक ही बार में पा लेंगे।
तो, इस मामले में खोज समय $\log_{2}8 + 1$ = 4 समय इकाइयाँ होगा, जो पहले की तुलना में काफी कम है।
ऊपर का उदाहरण इंडेक्सिंग की आवश्यकता से आपका परिचय कराता है। इंडेक्सिंग के बारे में विचार करने योग्य कुछ बिंदु ये हैं:
- मूल डेटा रेकॉर्ड्स पर क्रम केवल एक फ़ील्ड का उपयोग करके लगाया जा सकता है। और फिर फ़ील्ड एंट्रीज़ को उसी अनुसार इंडेक्स किया जा सकता है। केवल तभी जब आप उसी फ़ील्ड का उपयोग करके खोज करने का प्रयास करेंगे, आपको बेहतर खोज समय मिलेगा। (अत्यंत महत्वपूर्ण)
- इंडेक्स भी क्रमबद्ध होते हैं।
- इंडेक्स रेकॉर्ड में दो फ़ील्ड होते हैं (इंडेक्स फ़ाइल की संरचना)-
- मूल फ़ाइल की कुंजी
- मूल डेटा रेकॉर्ड्स में जहाँ कुंजी उपलब्ध है उस ब्लॉक का पॉइंटर
- इंडेक्स के माध्यम से खोज करने के लिए बाइनरी सर्च का उपयोग किया जाता है।
- इंडेक्स्ड एंट्रीज़ का उपयोग करके किसी रेकॉर्ड तक पहुँचने के लिए औसत ब्लॉक एक्सेस की संख्या-
$\log_{2}B_i + 1$ , जहाँ $B_i$ इंडेक्स्ड रेकॉर्ड्स में ब्लॉक्स की संख्या है - रिलेशन के किसी भी फ़ील्ड (प्राइमरी की, कैंडिडेट कीज़, नॉन-कीज़) पर इंडेक्स बनाया जा सकता है।
अब, मूल डेटा रेकॉर्ड्स के क्रम और आप इंडेक्स्ड फ़ाइल में कितने रेकॉर्ड्स बनाए रखने जा रहे हैं, इनके आधार पर कई इंडेक्सिंग स्कीम हो सकती हैं। अगले खंड में, आप सबसे लोकप्रिय स्कीम्स का अध्ययन करेंगे।
विभिन्न इंडेक्सिंग रणनीतियाँ:
- डेंस इंडेक्सिंग: यदि हर सर्च की वैल्यू के लिए एक इंडेक्स एंट्री बनाई जाती है, तो यह डेंस इंडेक्सिंग है। इसे दृश्य रूप से समझने के लिए निम्न डायग्राम पर विचार करें।

- स्पार्स इंडेक्सिंग: यदि कुछ रेकॉर्ड्स के लिए ही इंडेक्स एंट्री बनाई जाती है, तो यह स्पार्स इंडेक्सिंग है। इसे चित्रात्मक रूप से दर्शाने वाला एक डायग्राम यहाँ है।

ऊपर दिए गए डायग्राम दोनों इंडेक्सिंग स्कीम्स को समझना काफी आसान बना देते हैं। यहाँ एक महत्वपूर्ण बात यह है कि ऊपर दिया गया स्पार्स इंडेक्सिंग का उदाहरण डेंस और स्पार्स दोनों का संयोजन है। ऐसा इसलिए क्योंकि हर यूनिक सर्च की वैल्यू (1,2 और 3) के लिए एक इंडेक्स है, लेकिन हर डेटा रेकॉर्ड के लिए इंडेक्स नहीं है।
अब आप रेकॉर्ड्स के स्तर के आधार पर अन्य प्रकार की इंडेक्सिंग स्कीम्स का अध्ययन करेंगे। सिंगल-लेवल इंडेक्सिंग में, इंडेक्स फ़ाइल की संख्या केवल एक होती है। लेकिन, कभी-कभी इंडेक्स फ़ाइल का आकार इतना बड़ा हो जाता है कि स्वयं इंडेक्स फ़ाइल पर भी इंडेक्स बनाना पड़ता है। उस स्थिति में इसे मल्टी-लेवल इंडेक्सिंग कहा जाता है। आइए और गहराई में जाएँ।
लेवलिंग के आधार पर आगे की इंडेक्सिंग रणनीतियों का एक अवलोकन यहाँ है।
सिंगल-लेवल इंडेक्सिंग:
- प्राइमरी इंडेक्सिंग
- क्लस्टरिंग इंडेक्सिंग
- सेकेंडरी इंडेक्सिंग
मल्टी-लेवल इंडेक्सिंग:
- B ट्री
- B+ ट्री
आप सिंगल-लेवल इंडेक्सिंग से संबंधित सभी इंडेक्सिंग रणनीतियों का अध्ययन करेंगे। इस ट्यूटोरियल के अंत में, यदि आप चाहें, तो मल्टी-लेवल इंडेक्सिंग स्कीम्स का अन्वेषण करने के लिए एक लिंक होगा। अब प्राइमरी इंडेक्सिंग पर नज़र डालते हैं।
प्राइमरी इंडेक्सिंग:
प्राइमरी इंडेक्स एक आदेशित फ़ाइल है जिसकी रेकॉर्ड्स निश्चित लंबाई की होती हैं और जिनमें दो फ़ील्ड होते हैं:
- पहला फ़ील्ड डेटा फ़ाइल के प्राइमरी की के समान होता है।
- दूसरा फ़ील्ड उस डेटा ब्लॉक का पॉइंटर होता है जहाँ प्राइमरी की उपलब्ध है। - स्रोत
प्रत्येक ब्लॉक के पहले रेकॉर्ड के लिए बनाए गए इंडेक्स को ब्लॉक एंकर कहा जाता है। प्राइमरी इंडेक्सिंग में, इंडेक्स एंट्रीज़ की संख्या = मूल डेटा ब्लॉक्स की संख्या। प्राइमरी इंडेक्स का उपयोग करके औसत ब्लॉक एक्सेस की संख्या:
इसे और स्पष्ट रूप से समझने के लिए निम्न डायग्राम देखें: 
दाएँ तरफ़ का चित्र मूल डेटा रेकॉर्ड्स को कई ब्लॉक्स में विभाजित दिखाता है। ध्यान दें कि 1,2,3,...,9 वाली संख्या वाला कॉलम प्राइमरी कीज़ हैं। बाएँ तरफ़ का चित्र इंडेक्स्ड एंट्रीज़ को दर्शाता है जहाँ प्रत्येक एंट्री में शामिल है:
- प्रत्येक डेटा ब्लॉक की पहली एंट्री (ब्लॉक एंकर)
- दूसरी एंट्री ब्लॉक पॉइंटर को दर्शाती है।
एक पल रुकें और सोचें कि यह किस प्रकार की इंडेक्सिंग है (स्पार्स या डेंस)। अपने उत्तर पोस्ट करने के लिए comments सेक्शन का उपयोग करें।
अब आप क्लस्टरिंग इंडेक्सिंग का अध्ययन करेंगे।
क्लस्टरिंग इंडेक्सिंग:
क्लस्टरिंग इंडेक्स उस डेटा फ़ाइल पर बनाया जाता है जिसकी फ़ाइल रेकॉर्ड्स भौतिक रूप से किसी नॉन-की फ़ील्ड पर आदेशित होती हैं, जिसके प्रत्येक रेकॉर्ड के लिए भिन्न मान नहीं होते। इस फ़ील्ड को क्लस्टरिंग फ़ील्ड कहा जाता है, जिसके आधार पर इंडेक्सिंग की जाती है। इसी से इसका नाम पड़ा है - क्लस्टरिंग इंडेक्स।

डायग्राम समझना हमेशा आसान बना देते हैं। जैसा कि आप देख सकते हैं, मूल डेटा रेकॉर्ड्स किसी नॉन-की एट्रिब्यूट पर आदेशित हैं और नॉन-की एट्रिब्यूट के प्रत्येक भिन्न मान के लिए एक इंडेक्स एंट्री बनाई जाती है। इस स्कीम का उपयोग करके किसी विशेष रेकॉर्ड का पता लगाने के लिए आवश्यक औसत ब्लॉक एक्सेस की संख्या $\geq$ $\log_{2}B_i + 1$ है, जहाँ $B_i$ इंडेक्स्ड रेकॉर्ड्स में ब्लॉक्स की संख्या है। यहाँ $\geq$ चिह्न पर ध्यान दें।
क्लस्टरिंग इंडेक्स में, किसी विशेष की वाले ब्लॉक का पता लगाने के बाद, आपको अन्य ब्लॉक्स में भी जाना पड़ सकता है (जो ऊपर के चित्र से स्पष्ट है)।
आप सोचना चाहेंगे कि यह किस प्रकार की इंडेक्सिंग है (स्पार्स या डेंस)। अपने उत्तर पोस्ट करने के लिए comments सेक्शन का उपयोग करें। अब सेकेंडरी इंडेक्सिंग पढ़ते हैं।
सेकेंडरी इंडेक्सिंग:
मान लीजिए आपके डेटाबेस में Employee नाम की एक टेबल है। टेबल के निम्न एट्रिब्यूट्स हैं:
- employee_id
- employee_name
- employee_department
- employee_salary
employee_id इसकी प्राइमरी की है। अब, आपने पहले से ही इस टेबल पर employee_id के आधार पर प्राइमरी इंडेक्सिंग बना रखी है। लेकिन कोई एप्लिकेशन विकसित करते समय आपने पाया कि अधिकांश डेटाबेस क्वेरीज़ employee_name एट्रिब्यूट का उपयोग कर रही हैं। ऐसे में, प्राइमरी इंडेक्सिंग बहुत मददगार नहीं होगी, और employee_name से संबंधित सभी मानों के लिए अलग इंडेक्सिंग बनाए रखना अच्छा अभ्यास होगा। वैसे भी, कर्मचारी नाम डेटाबेस में क्रमबद्ध तरीके से मौजूद नहीं होंगे। इसलिए, उन पर इंडेक्सिंग करना कर्मचारी नामों से जुड़ी क्वेरीज़ को निश्चित रूप से तेज़ करेगा।
यह सेकेंडरी इंडेक्सिंग का एक क्लासिक उदाहरण है। आइए सेकेंडरी इंडेक्सिंग के लिए एक उपयुक्त चित्र भी बनाएँ:

यदि आपके पास इससे बेहतर प्रतिनिधित्व हो, तो उसे comments सेक्शन में निःसंकोच साझा करें।
अब आप देखेंगे कि PostgreSQL में इंडेक्स कैसे बनाए जा सकते हैं। यदि आप इसकी बुनियाद सीखना चाहते हैं, तो DataCamp का Joining Data in PostgreSQL कोर्स लें।
PostgreSQL में इंडेक्स बनाना
PostgreSQL डेटाबेस में इंडेक्स बनाना शुरू करने से पहले, आपको टेबल में कुछ डेटा चाहिए होगा। आइए Student नाम की एक सरल टेबल बनाते हैं जिसमें निम्न रेकॉर्ड्स हों:
- student_id
- student_name
- student_year
आप student_id को प्राइमरी की बनाएँगे, और छात्र नाम तथा छात्र वर्ष को null नहीं होने देंगे।
इसके लिए क्वेरी निम्न होगी:
CREATE TABLE STUDENT(
student_id TEXT PRIMARY KEY,
student_name TEXT NOT NULL,
student_year TEXT NOT NULL
);
टेबल सफलतापूर्वक बन जाने के बाद, आपको टेबल में उपयुक्त डेटा डालना होगा। सुविधा के लिए, आप यह .csv इस्तेमाल कर सकते हैं और उसे Student में इम्पोर्ट कर सकते हैं। PostgreSQL टेबल में किसी संगत .csv फ़ाइल को निम्न क्वेरी से इम्पोर्ट कर सकते हैं:
COPY STUDENT FROM '/path/to/csv/Student.csv' WITH (FORMAT csv);
ऊपर दी गई क्वेरी मानती है कि जिस .csv फ़ाइल से डेटा कॉपी किया जा रहा है, उसका नाम Student है।
अब डेटा पर नज़र डालते हैं। select * from STUDENT; चलाने पर निम्न रेकॉर्ड्स मिलते हैं: 
select क्वेरी को कुल 86 रेकॉर्ड्स लौटाने चाहिए। अब आप इंडेक्स बनाने की स्थिति में हैं। आप सिंगल-कॉलम इंडेक्स निम्न सिंटैक्स से बना सकते हैं:
CREATE INDEX index_name
ON table_name (column_name);
आइए student_id फ़ील्ड पर एक इंडेक्स बनाएँ (प्राइमरी इंडेक्सिंग)।
CREATE INDEX id_index
ON STUDENT (student_id);
मल्टी-कॉलम इंडेक्स भी बनाए जा सकते हैं:
CREATE INDEX id_index
ON STUDENT (student_id,student_name);
किसी इंडेक्स को आप निम्न सिंटैक्स से ड्रॉप कर सकते हैं:
DROP INDEX index_name;
STUDENT जैसी छोटी टेबल में इंडेक्सिंग क्या कर रही है, इसका एहसास करना कठिन है। लेकिन यदि टेबल बड़ी होती (जैसे किसी बड़े विश्वविद्यालय के समान रेकॉर्ड्स वाली डेटाबेस टेबल), तो इंडेक्सिंग निश्चित रूप से महत्वपूर्ण भूमिका निभाती।
आपने कर दिखाया!
अंत तक पहुँचने के लिए बधाई। इस ट्यूटोरियल में, आपने इंडेक्सिंग, उसकी आवश्यकता, और विभिन्न इंडेक्सिंग स्कीम्स के बारे में जाना। आपने यह भी देखा कि PostgreSQL में साधारण इंडेक्सिंग कैसे की जा सकती है।
लेकिन आपने इस ट्यूटोरियल में मल्टी-लेवल इंडेक्सिंग के बारे में नहीं पढ़ा। यदि आप उन्हें एक्सप्लोर करना चाहते हैं, तो निम्न कुछ उत्कृष्ट संसाधन हैं:
पर क्या इंडेक्सिंग का उपयोग हमेशा मददगार होता है? खैर, कुछ मामलों में इंडेक्सिंग का उपयोग करना उचित नहीं होता।

आशा है कि इस ट्यूटोरियल ने आपको इंडेक्सिंग की बुनियाद स्पष्ट करने में मदद की। अपनी रोचक खोजों के बारे में मुझे comments सेक्शन में बताइए।
DataCamp का Learn SQL Hub देखें।