प्रॉम्प्ट और दायरा
एक ऑर्डर्स लेक टेबल को बैच जॉब्स, स्ट्रीमिंग जॉब्स और एड-हॉक एनालिस्ट्स द्वारा पढ़ा जाता है। व्यवसाय को एक नेस्टेड फ़ील्ड, एक कॉलम का नाम बदलना (rename), और मंथली से डेली पार्टीशनिंग में क्रमिक परिवर्तन की आवश्यकता है। पुराने जॉब्स को एक साथ अपग्रेड नहीं किया जा सकता है, और सभी ऐतिहासिक फ़ाइलों को फिर से लिखना बहुत महंगा है। बताएं कि Iceberg इन परिवर्तनों को कैसे रिकॉर्ड करता है और पुराने व नए लेआउट के एक साथ मौजूद रहने के दौरान पाठकों (readers) के लिए सही डेटा कैसे सुनिश्चित करता है।
मान लें कि एक Iceberg Catalog और ऐसे इंजन उपलब्ध हैं जो लक्षित Iceberg संस्करण का समर्थन करते हैं। यह इंटरव्यू टेबल-फ़ॉर्मेट स्कीमा और पार्टीशन इवोल्यूशन का परीक्षण करता है, न कि किसी विशिष्ट Spark SQL सिंटैक्स का।
इंटरव्यूअर क्या मूल्यांकन कर रहा है
- क्या आप field IDs, Schema IDs, Partition Spec IDs, और snapshots में अंतर करते हैं।
- क्या आप समझाते हैं कि add, drop, rename, और चुनिंदा type promotions को पुरानी फ़ाइलों को फिर से लिखने की आवश्यकता क्यों नहीं होती है, साथ ही उनकी सीमाएं क्या हैं।
- क्या आप पार्टीशन लेआउट के सह-अस्तित्व और मल्टीपल स्पेक्स में प्लानिंग की व्याख्या करते हैं, जिसमें यह भी शामिल है कि rewrite कब अभी भी उपयोगी है।
- क्या आप कम्पैटिबिलिटी, परफॉरमेंस, समवर्ती-कमिट (concurrent-commit), और रोलबैक वैलिडेशन का प्रस्ताव करते हैं।
पहले स्पष्ट करने योग्य प्रश्न
- क्या रीडर्स Iceberg टेबल फ़ॉर्मेट का उपयोग कर रहे हैं, या केवल किसी डायरेक्टरी को Hive टेबल के रूप में मान रहे हैं? बाद वाला स्वचालित रूप से field-ID सिमेंटिक्स प्रदान नहीं करता है।
- क्या परिवर्तन टॉप-लेवल, नेस्टेड या पार्टीशन ट्रांसफ़ॉर्म है? नेस्टेड और पार्टीशन फ़ील्ड्स में अतिरिक्त बाधाएं (constraints) होती हैं।
- क्या पुराने रीडर्स पोज़ीशन के आधार पर कॉलम बाइंड करते हैं या पुराने स्कीमा को कैश करते हैं? पुष्टि करें कि इंजन Iceberg फ़ील्ड मैपिंग का सम्मान करते हैं।
- क्या लक्ष्य कम स्कैन, हॉटस्पॉट सुधार, या केवल लॉजिकल स्कीमा परिवर्तन है? पार्टीशन के लाभों के लिए क्वेरी साक्ष्य की आवश्यकता होती है।
30-सेकंड का उत्तर ढांचा
“Iceberg टेबल की स्थिति को वर्ज़न किए गए मेटाडेटा में संग्रहीत करता है और पोज़ीशन या रीसायकल किए गए नामों के बजाय गैर-पुन: प्रयोज्य (non-reused) field IDs के साथ कॉलम मैप करता है। एक स्कीमा परिवर्तन Schema ID बनाता है; एक पार्टीशन परिवर्तन Partition Spec ID बनाता है। पुरानी फ़ाइलें अपना लेआउट बनाए रखती हैं, नए राइट्स नए स्पेक का उपयोग करते हैं, और रीडर्स हिडन पार्टीशन प्रूनिंग (hidden partition pruning) का उपयोग करते हुए प्रत्येक स्पेक की योजना बनाते हैं। मैं कम्पैटिबिलिटी जांच चलाऊंगा, मेटाडेटा को परमाणु रूप से (atomically) प्रकाशित करूंगा, फिर पुराने और नए रीडर्स, नाम बदलने की शुद्धता, स्कैन की गई फ़ाइलों, विफल पुनnature-प्रयासों (failed retries) और स्नैपशॉट रोलबैक का परीक्षण करूंगा। ‘नो फ़ाइल रीराइट’ एक माइग्रेशन विशेषता है, शून्य प्रदर्शन लागत का वादा नहीं।”
चरण-दर-चरण विश्लेषण
1. कॉलम पहचान के लिए field IDs का उपयोग करें
Iceberg प्रत्येक फ़ील्ड को एक ID असाइन करता है जिसे टेबल में कभी भी दोबारा उपयोग नहीं किया जाता है। नाम बदलने पर नाम बदल जाता है जबकि रीडर्स अभी भी ID द्वारा मूल फ़ील्ड को ढूंढते हैं। हटाए गए नाम को फिर से जोड़ने पर एक नया ID मिलता है, इसलिए पुरानी फ़ाइलों के मान चुपचाप वापस नहीं आ सकते हैं। पोज़ीशन-आधारित फ़ॉर्मेट सुरक्षित रूप से डिलीट और रीऑर्डर को संभाल नहीं सकते; नाम का पुन: उपयोग भी डेटा को गलत तरीके से मैप कर सकता है।
Old schema: id=17, name="customer_id"
New schema: id=17, name="account_id"
Added field: id=42, name="region"2. Schema ID को field ID से अलग करें
एक field ID उत्तर देता है कि "यह कौन सा कॉलम है?" एक Schema ID उत्तर देता है कि "यह टेबल संरचना का कौन सा संस्करण है?" एक इवोल्यूशन एक नया स्कीमा ऑब्जेक्ट बनाता है और इसके Schema ID को वर्तमान बनाता है; स्नैपशॉट उस स्कीमा को रिकॉर्ड करते हैं जिसका उपयोग उनके लिखे जाने के समय किया गया था। रीडर्स कॉलम नामों के कैश्ड ऐरे पर सुरक्षित रूप से भरोसा नहीं कर सकते हैं।
3. तय करें कि कौन से स्कीमा परिवर्तन सुरक्षित हैं
Add, drop, rename, reorder, और चुनिंदा widening ऑपरेशंस समर्थित हैं, लेकिन प्रत्येक टाइप परिवर्तन सुरक्षित नहीं है। फ़ॉर्मेट वर्ज़न, मान सीमा (value range), और पार्टीशन ट्रांसफ़ॉर्म की जाँच करें। बकेट ट्रांसफ़ॉर्म द्वारा उपयोग किए जाने वाले फ़ील्ड को तब प्रमोट नहीं किया जा सकता है जब ट्रांसफ़ॉर्म का परिणाम बदल जाता है। मैप-की (map-key) संरचनात्मक परिवर्तनों में भी समानता की बाधाएं होती हैं।
Safe candidate: add an optional field, rename a non-partition field, int -> long when transform output is unchanged
Block or redesign: narrowing a type, changing bucket input semantics, dropping a field required by critical readers4. पुराने और नए पार्टीशन स्पेक्स को एक साथ रहने दें
पार्टीशन इवोल्यूशन एक नया Partition Spec ID बनाता है। पुरानी फ़ाइलें पुराने स्पेक को बनाए रखती हैं जबकि नई फ़ाइलें नए डिफ़ॉल्ट का उपयोग करती हैं। एक रीडर को प्रत्येक फ़ाइल की व्याख्या उसके स्पेक का उपयोग करके करनी चाहिए और परिणामों को जोड़ना चाहिए। हिडन पार्टीशनिंग क्वेरीज़ को दिनांक डायरेक्टरी को हार्ड-कोड करने के बजाय डेटा मानों पर प्रेडिकेट्स व्यक्त करने की अनुमति देती है।
5. क्वेरी परफॉरमेंस के विरुद्ध “नो रीराइट” का मूल्यांकन करें
मेटाडेटा इवोल्यूशन डेटा फ़ाइलों को फिर से लिखने से बचाता है, जिससे माइग्रेशन लागत कम होती है, लेकिन पुरानी फ़ाइलों में अभी भी पुराना भौतिक लेआउट होता है। एकाधिक स्पेक्स विभिन्न प्रूनिंग गुणवत्ता के साथ कई स्प्लिट प्लान बना सकते हैं। स्कैन की गई फ़ाइलों, प्लानिंग समय, पढ़े गए बाइट्स, टास्क स्केव (task skew), और छोटी फ़ाइलों की संख्या की तुलना करें। यदि पुराना लेआउट एक हॉटस्पॉट बना रहता है, तो यह दिखावा करने के बजाय कि लॉजिकल इवोल्यूशन ने भौतिक डेटा को पुनर्गठित किया है, एक सीमित रीराइट शेड्यूल करें।
6. परमाणु कमिट (atomic commits) और स्नैपशॉट के साथ प्रकाशन को सुरक्षित रखें
टेबल स्थिति को मेटाडेटा फ़ाइलों और स्नैपशॉट द्वारा दर्शाया जाता है; एक अपडेट स्वचालित रूप से वर्तमान मेटाडेटा पॉइंटर को प्रतिस्थापित करता है। वर्तमान संस्करण पढ़ें, उससे नया मेटाडेटा बनाएं और कमिट करें। टकराव होने पर, रीफ़्रेश करें और पुनः प्रयास करें। परिवर्तन रिकॉर्ड को एक स्नैपशॉट ID से बाँधें ताकि कोई ख़राब रोलआउट पुराने रीडर्स के लिए कम्पैटिबिलिटी विंडो को संरक्षित करते हुए सत्यापित स्नैपशॉट पर वापस आ सके।
उच्च गुणवत्ता वाला नमूना उत्तर
मैं कॉलम पहचान, संरचनात्मक संस्करण और भौतिक लेआउट को अलग करूंगा। Field IDs किसी नाम बदलने या पुन: व्यवस्थित करने से पुरानी-फ़ाइल के मानों को गलत तरीके से मैप होने से रोकते हैं; एक Schema ID संरचनात्मक संस्करण रिकॉर्ड करता है; एक Partition Spec ID पार्टीशन ट्रांसफ़ॉर्म रिकॉर्ड करता है। region जोड़ना या customer_id का नाम बदलना मेटाडेटा का काम है, न कि फ़ाइल रीराइट, लेकिन मैं पहले सत्यापित करूंगा कि प्रत्येक इंजन field ID द्वारा पढ़ता है।
मंथली-से-डेली पार्टीशनिंग के लिए, मैं एक नया स्पेक बनाऊंगा और मौजूदा फ़ाइलों पर पुराने स्पेक को बनाए रखते हुए नए राइट्स के लिए इसका उपयोग करूंगा। प्लानर को प्रत्येक स्पेक के पार्टीशन एक्सप्रेशन को लागू करना चाहिए और स्प्लिट्स को मर्ज करना चाहिए। प्रकाशित करने से पहले, मैं एक पुराना-रीडर/नया-रीडर मैट्रिक्स चलाऊंगा, नाम बदलने के दौरान मानों की तुलना करूंगा, स्कैन की गई फ़ाइलों और बाइट्स को मापूँगा, और एक अलग शाखा (isolated branch) या कैटलॉग लेनदेन से कमिट करूंगा। यदि विरोध या क्वेरी रिग्रेशन दिखाई देते हैं, तो स्नैपशॉट द्वारा रोलबैक करें; यदि पुराना लेआउट धीमा रहता है, तो बाद में एक बजटेड रीराइट चलाएं।
सामान्य गलतियाँ और सुधार
- गलती → कॉलम का नाम बदलने को फ़ाइल-पोज़ीशन परिवर्तन के रूप में मानना → यह क्यों विफल होता है → पोज़ीशन बाइंडिंग गलत मान संलग्न कर सकती है → सुधार → स्थिर फ़ील्ड पहचान की व्याख्या करें और इंजन मैपिंग को सत्यापित करें।
- गलती → पार्टीशन इवोल्यूशन के बाद केवल नई निर्देशिकाओं को स्कैन करना → यह क्यों विफल होता है → पुरानी फ़ाइलें टेबल का हिस्सा बनी रहती हैं और परिणाम अधूरे हो सकते हैं → सुधार → प्रत्येक Partition Spec रखें और स्पेक-सचेत प्लानिंग का उपयोग करें।
- गलती → “नो रीराइट” को “शून्य परफॉरमेंस लागत” मानना → यह क्यों विफल होता है → एकाधिक स्प्लिट्स और पुराना लेआउट अभी भी स्कैन बढ़ा सकते हैं → सुधार → प्लानिंग, फ़ाइलों, बाइट्स और स्केव को मापें; यदि आवश्यक हो तो नियंत्रित बैचों में रीराइट करें।
- गलती → वर्तमान मेटाडेटा को सीधे अधिलेखित (overwrite) करना → यह क्यों विफल होता है → समवर्ती कमिट या पुनः प्रयास अपडेट खो सकते हैं → सुधार → पढ़े गए संस्करण से परमाणु रूप से कमिट करें, टकराव पर रीफ़्रेश करें, और रोलबैक बिंदु बनाए रखें।
अनुवर्ती प्रश्न और उत्तर
आप किसी फ़ील्ड को हटाने के बाद उसी नाम का दोबारा उपयोग क्यों नहीं कर सकते?
आप नाम को फिर से जोड़ सकते हैं, लेकिन उसे एक नया field ID प्राप्त होना चाहिए। पुरानी ID का पुन: उपयोग करने से पुरानी फ़ाइल के मान नए फ़ील्ड के रूप में दिखाई दे सकते हैं, जो ड्रॉप सिमेंटिक्स का उल्लंघन करता है। पुरानी फ़ाइलों, नई फ़ाइलों और फिर से बनाए गए नाम को असाइन की गई ID का परीक्षण करें।
क्या int-to-long प्रमोशन हमेशा सुरक्षित होता है?
नहीं। फ़ॉर्मेट वर्ज़न, मान सीमा, डाउनस्ट्रीम प्रकार, और क्या फ़ील्ड पार्टीशन ट्रांसफ़ॉर्म में उपयोग होती है, इसकी जाँच करें। यदि कोई बकेट या अन्य ट्रांसफ़ॉर्म अपना आउटपुट बदलता है, तो पुराने और नए पार्टीशन सिमेंटिक्स भिन्न हो सकते हैं; परिवर्तन को ब्लॉक करें या पहले एक नया स्पेक डिज़ाइन करें।
क्या मासिक पुरानी फ़ाइलें और दैनिक नई फ़ाइलें छूटी हुई पंक्तियों (missed rows) का कारण बन सकती हैं?
सही कार्यान्वयन में नहीं। रीडर प्रत्येक फ़ाइल की उसके Partition Spec के साथ व्याख्या करता है, उस स्पेक के भीतर प्रून करता है, और परिणामों को जोड़ता है। इवोल्यूशन सीमा को पार करने वाली रेंज क्वेरीज़ का परीक्षण करें और एक पूर्ण-स्कैन संदर्भ के साथ पंक्ति सेट की तुलना करें।
आप अभी भी डेटा फ़ाइलों को कब फिर से लिखते (rewrite करते) हैं?
डेटा फ़ाइलों को तब फिर से लिखें जब पुराना लेआउट लगातार स्कैन, स्केव, छोटी फ़ाइलों या स्टोरेज लागत का कारण बनता है। स्कीमा या पार्टीशन मेटाडेटा इवोल्यूशन को स्वयं इसकी आवश्यकता नहीं होती है। रीराइट को स्नैपशॉट, समवर्ती नियंत्रण और एक बजट दें ताकि भौतिक सफ़ाई प्रतिवर्ती (reversible) बनी रहे।