प्रतिनिधि इंटरव्यू विषय

डेटा इंजीनियरिंग इंटरव्यू: आप लेकहाउस में स्माल-फाइल्स (Small-Files) की समस्या का निदान और समाधान कैसे करते हैं?

डेटाकठिन
Offer.cc संपादकीय टीमप्रकाशित अपडेट किया गया

प्रश्न

20 TiB की एक Iceberg इवेंट टेबल में प्रतिदिन 200 GiB डेटा आता है, लेकिन लगभग 80,000 Parquet फाइलें बन जाती हैं, और क्वेरी प्लानिंग का समय लगातार बढ़ रहा है। आप इसके कारण का पता कैसे लगाएंगे, नई छोटी फाइलों को बनने से कैसे रोकेंगे, और बैकलाग को सुरक्षित रूप से कैसे कॉम्पैक्ट करेंगे?

प्रांप्ट और लागू संदर्भ

ऑब्जेक्ट स्टोरेज पर एक Apache Iceberg इवेंट टेबल में 20 TiB सक्रिय डेटा है। एक स्ट्रीमिंग जॉब एक-मिनट के माइक्रो-बैचेस कमिट करती है। यह प्रतिदिन लगभग 200 GiB जोड़ती है लेकिन लगभग 80,000 Parquet डेटा फाइलें बनाती है जिनका मीडियन आकार केवल 3 MiB है। क्वेरी p95 हाल ही में 20 सेकंड से बढ़कर 95 सेकंड हो गया है, जबकि प्लानिंग चरण 4 सेकंड से बढ़कर 32 सेकंड हो गया है। व्यवसाय को नियर-रियल-टाइम इनजेशन बनाए रखना है, सात दिनों का टाइम ट्रैवल सुरक्षित रखना है, और स्टोरेज से टेबल ऑब्जेक्ट्स को सीधे कभी नहीं हटाना है।

बताएं कि आप यह कैसे सिद्ध करेंगे कि रिग्रेशन का मुख्य कारण छोटी फाइलें हैं, राइट और पार्टिशनिंग कारणों का पता कैसे लगाएंगे, इसकी वृद्धि को कैसे रोकेंगे, और मौजूदा फाइलों को सुरक्षित रूप से कैसे कॉम्पैक्ट करेंगे। इसमें कॉनक्रेन्सी कंट्रोल, संसाधन बजटिंग, रोलबैक और स्वीकृति मानदंड (acceptance criteria) शामिल करें।

सभी क्षमताएं, फाइलों की संख्या, लेटेंसी और थ्रूपुट मान इंटरव्यू की मान्यताएं हैं, सार्वभौमिक बेंचमार्क नहीं। यह प्रश्न डेटा इंजीनियरिंग, एनालिटिक्स प्लेटफॉर्म, लेकहाउस इन्फ्रास्ट्रक्चर और डेटा-प्लेटफॉर्म SRE भूमिकाओं के लिए उपयुक्त है। इसकी मुख्य दक्षता डेटा लेआउट और टेबल रखरखाव है, इसलिए श्रेणी data है; यह केवल Spark-कॉन्फ़िगरेशन या ऑब्जेक्ट-स्टोरेज ऑपरेशंस का प्रश्न नहीं है।

इंटरव्यूअर क्या मूल्यांकन कर रहा है

पहला, क्या उम्मीदवार एक साक्ष्य श्रृंखला (evidence chain) बना सकता है? केवल फाइलों की अधिक संख्या कार्य-कारण संबंध (causality) स्थापित नहीं करती है। सक्रिय फाइलों की संख्या, आकार वितरण (size distribution), पार्टिशन स्केव, मैनिफेस्ट-रीडिंग समय, टास्क स्टार्टअप और फाइल-ओपन ओवरहेड को क्वेरी प्लानिंग और स्कैनिंग से अलग-अलग संबंधित किया जाना चाहिए।

दूसरा, क्या उम्मीदवार बैकलाग फिक्स और रोकथाम के बीच अंतर कर सकता है? कॉम्पेक्शन मौजूदा फाइलों को संभालता है। यदि माइक्रो-बैच आवृत्ति, राइटर की संख्या, डेटा वितरण और अत्यधिक बारीक पार्टिशनिंग अपरिवर्तित रहती है, तो टेबल फिर से खंडित (fragment) हो जाएगी।

तीसरा, क्या उम्मीदवार टेबल-फॉर्मेट ट्रांजेक्शन सीमाओं का सम्मान करता है? Iceberg कॉम्पेक्शन डेटा फाइलों को फिर से लिखता है और एक नया स्नैपशॉट कमिट करता है। पुराने स्नैपशॉट अभी भी पुरानी फाइलों का संदर्भ दे सकते हैं, इसलिए मेटाडेटा के पीछे ऑब्जेक्ट्स को हटाना असुरक्षित है।

चौथा, क्या उम्मीदवार सीमित ट्रेड-ऑफ (bounded trade-offs) कर सकता है? बिन पैकिंग मुख्य रूप से फाइलों के आकार को बदलती है। सॉर्टिंग या Z-ऑर्डरिंग क्लस्टरिंग को भी बदलती है और प्रूनिंग में सुधार कर सकती है, लेकिन इसमें अधिक शफल, सॉर्टिंग और अस्थायी स्टोरेज की लागत आती है।

पांचवां, क्या उम्मीदवार एक परिचालन योजना (operating plan) की मात्रा निर्धारित कर सकता है? एक मजबूत उत्तर प्रतिदिन दोबारा लिखे गए बाइट्स, लक्षित फाइलों की संख्या, जॉब विंडो और संघर्ष के जोखिम (conflict risk) का अनुमान लगाता है, फिर रोलआउट का विस्तार करने का निर्णय लेने के लिए शुद्धता और प्रदर्शन मेट्रिक्स दोनों का उपयोग करता है।

उत्तर देने से पहले स्पष्ट करने वाले प्रश्न

  • “छोटा” को कौन सा लक्ष्य परिभाषित करता है? write.target-file-size-bytes पढ़ें, फिर क्वेरी सेलेक्टिविटी, प्रति-पार्टिशन दैनिक वॉल्यूम और इंजन परीक्षणों का उपयोग करके थ्रेशोल्ड चुनें। एक निश्चित आकार हर टेबल के लिए सही नहीं होता है।
  • क्या 80,000 फाइलें वर्तमान स्नैपशॉट में सक्रिय हैं या ऐतिहासिक स्नैपशॉट में गिनी गई हैं? क्वेरी पाथ के लिए files से शुरुआत करें; रिटेंशन और स्टोरेज लागत के लिए all_files और स्नैपशॉट संदर्भों का उपयोग करें।
  • क्या लेटेंसी प्लानिंग में है या स्कैनिंग में? प्लानिंग हिस्सेदारी का बढ़ना मैनिफेस्ट और फाइल टास्क की ओर इशारा करता है। गिरता हुआ स्कैन थ्रूपुट स्केव, डिलीट फाइलों, कम्प्रेशन, कॉलम स्टैटिस्टिक्स और डाउनस्ट्रीम संसाधनों की जांच करने की भी मांग करता है।
  • पार्टिशन स्पेक और राइट डिस्ट्रीब्यूशन क्या हैं? उच्च-कार्डिनैलिटी या अत्यधिक बारीक समय पार्टिशन कभी भी लक्ष्य-आकार की फाइल जमा नहीं कर सकते हैं। अत्यधिक पैरेलल राइटर्स प्रत्येक आंशिक रूप से भरी हुई फाइल कमिट कर सकते हैं।
  • क्या टेबल कॉपी-ऑन-राइट या मर्ज-ऑन-रीड का उपयोग करती है? मर्ज-ऑन-रीड स्थिति या समानता डिलीट फाइलें जमा कर सकता है, इसलिए केवल डेटा फाइलों को कॉम्पैक्ट करना पर्याप्त नहीं हो सकता है।
  • किन पार्टिशन्स में अभी भी देर से डेटा (late data) आता है? बंद, कोल्ड पार्टिशन्स को प्राथमिकता दें। हॉट पार्टिशन्स के लिए छोटे फाइल समूहों, नियंत्रित कॉनक्रेन्सी और संघर्ष पुनः प्रयासों (conflict retries) की आवश्यकता होती है।
  • सात दिन के रिटेंशन का क्या अर्थ है? स्नैपशॉट क्वेरीबिलिटी, ब्रांच या टैग रिटेंशन, और ऑब्जेक्ट-स्टोर लाइफसाइकिल की अलग-अलग पुष्टि करें। एक डायरेक्टरी डिलीशन इन तीनों का विकल्प नहीं हो सकता।

30-सेकंड उत्तर ढांचा (30-Second Answer Framework)

“मैं वर्तमान Iceberg स्नैपशॉट से सक्रिय फाइलों, आकार पर्सेंटाइल और पार्टिशन्स की प्रोफाइलिंग करूंगा, फिर प्लानिंग को स्कैनिंग से अलग करूंगा। 200 GiB प्रति दिन पर, लगभग 400 आदर्श 512 MiB फाइलों के मुकाबले 80,000 फाइलें होना माइक्रो-बैचेस, राइटर्स और पार्टिशन ग्रैन्युलैरिटी को पहला संदिग्ध बनाता है।

मैं बैचेस को बड़ा करके, पार्टिशन की द्वारा वितरित करके और राइटर काउंट को नियंत्रित करके नए विखंडन (fragmentation) को रोकूंगा। फिर मैं सीमित कॉनक्रेन्सी के साथ एक कोल्ड पार्टिशन को बिन-पैक करूंगा, और सॉर्टिंग केवल तभी करूंगा जब प्रूनिंग परीक्षण इसे उचित ठहराते हों। कॉम्पेक्शन एक नया स्नैपशॉट कमिट करता है; पुरानी फाइलें सात-दिवसीय रिटेंशन का पालन करती हैं और उन्हें कभी सीधे नहीं हटाया जाता है। डेटा समाधान (data reconciliation), फाइल पर्सेंटाइल, प्लानिंग और क्वेरी p95, लैग और संघर्ष यह निर्धारित करते हैं कि रोलआउट का विस्तार किया जाए या नहीं।”

चरण-दर-चरण गहन विश्लेषण (Step-by-Step Deep Dive)

चरण 1: वर्तमान स्नैपशॉट से फाइलों की प्रोफाइलिंग करें

ऑब्जेक्ट-स्टोर डायरेक्टरी को रिकर्सिव रूप से लिस्ट करने के बजाय Iceberg मेटाडेटा को क्वेरी करें। डायरेक्टरी में केवल ऐतिहासिक स्नैपशॉट द्वारा संदर्भित फाइलें या अनाथ ऑब्जेक्ट्स (orphaned objects) हो सकते हैं, इसलिए यह उसका प्रतिनिधित्व नहीं करती है जो एक वर्तमान क्वेरी प्लान करती है। निम्नलिखित SQL एक Spark और Iceberg कैटलॉग को दर्शाता है; वास्तविक इंजन के अनुसार कैटलॉग नाम और पर्सेंटाइल फ़ंक्शन को अनुकूलित करें:

sql
SELECT
  partition,
  COUNT(*) AS active_files,
  SUM(file_size_in_bytes) AS active_bytes,
  percentile_approx(file_size_in_bytes, array(0.5, 0.9, 0.99)) AS size_percentiles
FROM lakehouse.analytics.events.files
GROUP BY partition
ORDER BY active_files DESC;

वर्तमान स्नैपशॉट ID, डेटा-फाइल और डिलीट-फाइल काउंट, मैनिफेस्ट काउंट, पार्टिशन द्वारा फाइल-आकार पर्सेंटाइल, और उम्मीदवार थ्रेशोल्ड से नीचे की फाइलों के प्रतिशत को रिकॉर्ड करें। एक औसत (mean) लॉन्ग टेल को छुपाता है: एक पार्टिशन में कुछ बड़ी फाइलें और 1-से-3 MiB की हजारों फाइलें हो सकती हैं। कम से कम, p50, p90, p99 और एक हिस्टोग्राम का निरीक्षण करें।

क्वेरी p95 को कैटलॉग और मैनिफेस्ट रिज़ॉल्यूशन, फाइल प्लानिंग, टास्क शेड्यूलिंग, टाइम टू फर्स्ट बाइट, और स्कैनिंग में विभाजित करें। कार्य-कारण का मामला तब अधिक मजबूत हो जाता है जब फाइल काउंट और प्लानिंग का समय एक साथ बढ़ते हैं और समान कुल बाइट्स वाला एक परीक्षण पार्टिशन कॉम्पेक्शन के बाद काफी तेजी से प्लान होता है। यदि प्लानिंग स्थिर है लेकिन स्कैनिंग धीमी हो जाती है, तो इसके बजाय सेलेक्टिविटी, कॉलम स्टैटिस्टिक्स, डिलीट फाइलों, स्केव और कंप्यूट संसाधनों की जांच करें।

चरण 2: राइट पाथ में पुनर्जनन (Regeneration) के कारण का पता लगाएं

यह परिदृश्य प्रतिदिन 1,440 एक-मिनट के बैच उत्पन्न करता है। अस्सी हजार फाइलें औसतन प्रति बैच लगभग 56 फाइलें हैं। जब प्रत्येक राइटर या राइटर-पार्टिशन संयोजन को बहुत कम डेटा प्राप्त होता है, तो 512 MiB का लक्ष्य निर्धारित करने से 3 MiB का आउटपुट पूरी फाइल में नहीं बदल सकता है। write.target-file-size-bytes एक लक्ष्य है, यह गारंटी नहीं है कि प्रत्येक फाइल इस तक पहुंचेगी।

मूल कारण अक्सर एक संयोजन होता है: माइक्रो-बैचेस बहुत लगातार होते हैं; प्रत्येक बैच के लिए अपस्ट्रीम पैरेललिज्म अत्यधिक होता है; पंक्तियों को लिखने से पहले टेबल पार्टिशन की द्वारा क्लस्टर नहीं किया जाता है; प्रति घंटा, टेनेंट, या उपयोगकर्ता आयाम टेबल को ओवर-पार्टिशन करते हैं; हॉट कीज़ स्केव का कारण बनती हैं; पुनः प्रयास (retries) कमिट जोड़ते हैं; या मर्ज-ऑन-रीड अपडेट्स डिलीट-फाइल का भार (debt) बनाते हैं।

प्रति पार्टिशन “छोटा” की व्याख्या करें। एक वैध कम-मात्रा वाला पार्टिशन जो प्रतिदिन केवल 40 MiB प्राप्त करता है, कभी भी 512 MiB की फाइल नहीं भर सकता है। एक छोटा लक्ष्य स्वीकार करें, पार्टिशन स्पेक को मोटा (coarsen) करें, या हमेशा कॉम्पेक्शन आवृत्ति बढ़ाने के बजाय बकेट्स या छिपी हुई पार्टिशनिंग (hidden partitioning) का उपयोग करें।

चरण 3: उसी विखंडन का उत्पादन बंद करें

कैनरी में राइट-साइड का सबसे छोटा बदलाव करें। फ्रेशनेस SLA के भीतर, एक-मिनट के कमिट्स को एक बड़े ट्रिगर बैच में संयोजित करें। Iceberg पार्टिशन की द्वारा पंक्तियों को हैश- या रेंज-वितरित करें। अधिकतम क्लस्टर पैरेललिज्म के बजाय प्रति बैच बाइट्स से राइटर काउंट चुनें। उच्च-कार्डिनैलिटी कॉलम पर सीधे पार्टिशनिंग से बचें।

वास्तविक कम्प्रेशन अनुपात, पंक्ति की चौड़ाई, क्वेरी सेलेक्टिविटी और प्रति पार्टिशन दैनिक वॉल्यूम के विरुद्ध लक्षित फाइल आकार का परीक्षण करें। परिदृश्य 512 MiB, या 536,870,912 बाइट्स को एक उम्मीदवार के रूप में उपयोग करता है क्योंकि Iceberg डिफ़ॉल्ट एक उचित प्रारंभिक बिंदु प्रदान करता है। यह 128 MiB, 256 MiB, या किसी बड़े मान को खारिज नहीं करता है। यदि कोई पार्टिशन लक्ष्य से बहुत छोटा है, तो पार्टिशन स्पेक को विकसित (evolve) करें। यदि पर्याप्त डेटा मौजूद है लेकिन प्रत्येक राइटर को कम पंक्तियाँ मिलती हैं, तो वितरण और पैरेललिज्म को ठीक करें।

दो समान रूप से लोड किए गए पार्टिशन्स पर A/B तुलना चलाएं। समान डेटा वॉल्यूम पर फाइल काउंट, आकार वितरण, कमिट लेटेंसी, स्ट्रीम-प्रोसेसिंग लैग और विफलता रिकवरी की तुलना करें। बैकलाग कॉम्पेक्शन केवल तभी टिकाऊ बनता है जब नई-फाइल जनरेशन दर में भौतिक रूप से गिरावट आती है।

चरण 4: लाभ और संघर्ष जोखिम द्वारा कॉम्पेक्शन को सीमित करें

पहले पास के लिए, एक ऐसा कोल्ड पार्टिशन चुनें जिसकी लेट-डेटा और व्यावसायिक-सुधार विंडो बंद हो चुकी हों, और कम से कम वर्तमान में लिखे जा रहे घंटे को बाहर रखें। क्या कोई पार्टिशन अभी भी बदल सकता है और क्या स्नैपशॉट सात दिनों के लिए बनाए रखे जाते हैं, ये अलग-अलग समयसीमाएं हैं। बिन पैकिंग से शुरुआत करें क्योंकि तत्काल लक्ष्य कम मेटाडेटा और फाइल-ओपन ओवरहेड है। सॉर्टिंग या Z-ऑर्डरिंग में केवल तभी अपग्रेड करें जब सामान्य फ़िल्टर कॉलम फाइलों में भारी रूप से ओवरलैप होते हैं और एक बेंचमार्क अतिरिक्त शफल को उचित ठहराता है।

sql
CALL lakehouse.system.rewrite_data_files(
  table => 'analytics.events',
  strategy => 'binpack',
  options => map(
    'target-file-size-bytes', '536870912',
    'min-input-files', '5',
    'max-concurrent-file-group-rewrites', '3',
    'partial-progress.enabled', 'true'
  ),
  where => 'event_date = DATE ''2026-07-10'''
);

where प्रेडिकेट उन फाइलों का चयन करता है जिनमें मेल खाने वाली पंक्तियाँ हो सकती हैं। इसे पार्टिशन सीमाओं के साथ संरेखित करें और निष्पादन से पहले उम्मीदवार बाइट्स का निरीक्षण करें। फाइल समूह काम की प्रत्येक इकाई को सीमित करते हैं। नियंत्रित कॉनक्रेन्सी ऑब्जेक्ट स्टोरेज, शफल और क्वेरी क्लस्टर को एक साथ संतृप्त होने से रोकती है। आंशिक प्रगति (partial progress) समूहों को अलग-अलग कमिट करती है, जिससे संघर्ष को पुनः प्रयास करने की लागत कम हो जाती है, लेकिन यह कई स्नैपशॉट बनाती है और इसके लिए समूह-स्तरीय निगरानी और रोलबैक की आवश्यकता होती है।

यदि हॉट पार्टिशन्स से बचा नहीं जा सकता है, तो समय सीमा और फाइल समूहों को छोटा करें, शेड्यूलिंग को इडेम्पोटेंट बनाएं, और डेटा-फाइल संघर्षों को पुनः प्रयास करने योग्य मेटाडेटा कमिट संघर्षों से अलग करें। ओवरलैपिंग टेबल रेंज वाले दो कॉम्पेक्शन जॉब कभी न चलाएं।

चरण 5: लक्ष्य फाइल गणना, I/O, और विंडो का अनुमान लगाएं

200 GiB को 512 MiB से विभाजित करने पर लगभग 400 लक्षित फाइलों की एक आदर्श संख्या मिलती है। पार्टिशन सीमाएं, कम्प्रेशन, और शेष भाग वास्तविक संख्या को कुछ अधिक बना देते हैं। यह अनुमान परिमाण की त्रुटियों (order-of-magnitude errors) को पकड़ता है; यह ठीक 400 आउटपुट का वादा नहीं है।

एक पूर्ण दैनिक पार्टिशन को कॉम्पैक्ट करने में लगभग 200 GiB पढ़ा जाता है और लगभग 200 GiB लिखा जाता है, या लगभग 400 GiB का डेटा I/O, साथ ही शफल, अस्थायी स्टोरेज, मेटाडेटा और पुनः प्रयास होते हैं। यदि कोई बेंचमार्क इनपुट बाइट्स द्वारा 100 MiB/s के निरंतर एंड-टू-एंड थ्रूपुट को मापता है, तो आदर्श अवधि है:

text
200 GiB * 1024 MiB/GiB / 100 MiB/s = 2,048 s ≈ 34.1 min

स्केव, समवर्ती प्रश्नों (concurrent queries), और पुनः प्रयासों के लिए मार्जिन जोड़ें। 60-से-90-मिनट की विंडो एक उचित परिदृश्य बजट है, साथ ही उम्मीदवार बाइट्स, समवर्ती फाइल समूहों, ऑब्जेक्ट-स्टोर अनुरोध दर और अस्थायी डिस्क पर सीमाएं हैं। यदि 200 GiB आने पर कॉम्पेक्शन प्रतिदिन केवल 150 GiB प्रोसेस कर सकता है, तो बैकलाग बढ़ना ही है। पहले टिकाऊ थ्रूपुट बढ़ाएं या नई-फाइल निर्माण को कम करें।

चरण 6: भौतिक क्लीनअप से स्नैपशॉट रिटेंशन को अलग करें

कॉम्पेक्शन के बाद, नया स्नैपशॉट बड़ी फाइलों को संदर्भित करता है। पुराने स्नैपशॉट को पहले से पढ़ रही एक क्वेरी अभी भी समाप्त हो सकती है, और सात-दिवसीय टाइम-ट्रैवल को अभी भी पुरानी फाइलों की आवश्यकता होती है। मूल Parquet ऑब्जेक्ट्स को सीधे हटाने से दोनों व्यवहार बाधित होंगे।

नए स्नैपशॉट को मान्य करें और expire_snapshots चलाने से पहले एक पूर्ण व्यावसायिक चक्र का निरीक्षण करें। सात-दिवसीय विंडो, आवश्यक ब्रांचेस या टैग्स, और न्यूनतम स्नैपशॉट संख्या को सुरक्षित रखें। स्नैपशॉट समाप्ति केवल उन फाइलों को हटाती है जिनकी अब किसी भी बनाए रखे गए स्नैपशॉट को आवश्यकता नहीं है। अनाथ फाइलें (orphan files) एक अलग वर्ग हैं: कोई टेबल मेटाडेटा उन्हें संदर्भित नहीं करता है। remove_orphan_files को अलग से चलाएं, dry_run से शुरुआत करें, एक रूढ़िवादी older_than चुनें, और हटाने से पहले पाथ स्कीम्स, प्राधिकारियों (authorities), और सबसे लंबे इन-फ्लाइट राइट को सत्यापित करें।

स्नैपशॉट समाप्ति कॉम्पेक्शन नहीं है, और अनाथों की सफाई पुराने स्नैपशॉट संदर्भों को समाप्त करने का विकल्प नहीं है। तीनों को स्वतंत्र शेड्यूल, अनुमतियां और ऑडिट रिकॉर्ड दें।

चरण 7: कैनरी, सत्यापन, और स्टॉप कंडीशंस परिभाषित करें

प्री-कॉम्पेक्शन स्नैपशॉट और उम्मीदवार पार्टिशन को पिन करें। पंक्ति संख्या (row count), डिस्टिंक्ट बिजनेस-की काउंट, महत्वपूर्ण राशि या इवेंट एग्रीगेट्स, न्यूनतम और अधिकतम इवेंट समय, और नल काउंट्स रिकॉर्ड करें। बाद में उसी लॉजिकल रेंज की पुनर्गणना करें। केवल कुल पंक्ति संख्या एक डुप्लिकेट द्वारा ऑफसेट किए गए एक खोए हुए रो को छुपा सकती है, इसलिए महत्वपूर्ण टेबल्स में बकेटेड चेकसम या बिजनेस-की के नमूने जोड़े जाने चाहिए।

प्रदर्शन के लिए, सक्रिय फाइल काउंट, p50/p90/p99 आकार, मैनिफेस्ट काउंट, प्लानिंग p50/p95, एंड-टू-एंड क्वेरी p95, स्कैन किए गए बाइट्स, फिर से लिखे गए बाइट्स और संसाधन लागत की तुलना करें। परिचालन मेट्रिक्स में छोटी-फाइल उत्पादन दर, कॉम्पेक्शन लैग, विफल फाइल समूह, कमिट संघर्ष, स्नैपशॉट काउंट और रिक्लेम करने योग्य बाइट्स शामिल हैं।

यदि शुद्धता में अंतर आता है, प्लानिंग समय में सुधार नहीं होता है, लागत इनजेशन SLA में बाधा डालती है, या कॉम्पेक्शन थ्रूपुट नए विखंडन दर से नीचे रहता है, तो विस्तार रोक दें। एक टेबल स्नैपशॉट मेटाडेटा पॉइंटर को रोल बैक कर सकता है, लेकिन यह पहले से पूर्ण स्नैपशॉट समाप्ति और भौतिक विलोपन को स्वयं उलट नहीं सकता है।

उच्च गुणवत्ता वाला नमूना उत्तर (High-Quality Sample Answer)

“मैं कॉम्पेक्शन चलाकर शुरुआत नहीं करूंगा। मैं पहले बॉटलनेक को सिद्ध करूंगा। एक ऑब्जेक्ट-स्टोर डायरेक्टरी ऐतिहासिक और अनाथ फाइलों को मिलाती है, इसलिए मैं पार्टिशन द्वारा सक्रिय फाइलों, कुल बाइट्स और p50/p90/p99 आकारों को मापने के लिए वर्तमान Iceberg स्नैपशॉट की files मेटाडेटा टेबल का उपयोग करूंगा। मैं फिर कैटलॉग और मैनिफेस्ट रिज़ॉल्यूशन, टास्क प्लानिंग, फाइल ओपनिंग और स्कैनिंग को अलग करूंगा। परिदृश्य में, 200 GiB प्रति दिन 3 MiB मीडियन के साथ 80,000 फाइलें बनाता है। एक 512 MiB उम्मीदवार लक्ष्य का अर्थ लगभग 400 आदर्श फाइलें हैं, इसलिए राइट लेआउट एक मजबूत सुराग है, लेकिन मैं फिर भी पुष्टि करूंगा कि समान बाइट्स वाला एक कॉम्पैक्टेड पार्टिशन तेजी से प्लान करता है।

इसके बाद मैं पुनर्जनन को ठीक करूंगा। प्रतिदिन 1,440 एक-मिनट के बैच हैं और प्रति बैच लगभग 56 फाइलें हैं। मैं राइटर पैरेललिज्म, पार्टिशन कार्डिनैलिटी, प्री-राइट डिस्ट्रीब्यूशन, स्केव, पुनः प्रयास और मर्ज-ऑन-रीड डिलीट फाइलों का निरीक्षण करूंगा। फ्रेशनेस SLA के भीतर, मैं कमिट बैचेस को बड़ा करूंगा, पार्टिशन की द्वारा हैश- या रेंज-वितरित करूंगा, और बैच बाइट्स से राइटर काउंट का आकार तय करूंगा। 512 MiB मान केवल एक प्रारंभिक बिंदु है। एक कम-मात्रा वाला पार्टिशन जो इसे नहीं भर सकता, उसे एक मोटे पार्टिशन या छोटे लक्ष्य की आवश्यकता होती है।

बैकलाग के लिए, मैं rewrite_data_files बिन पैकिंग, एक पार्टिशन प्रेडिकेट, सीमित फाइल-ग्रुप कॉनक्रेन्सी, और एक उम्मीदवार-बाइट कैप के साथ एक कोल्ड पार्टिशन को कैनरी करूंगा। मैं केवल तभी सॉर्टिंग या Z-ऑर्डरिंग का उपयोग करूंगा जब सामान्य फ़िल्टर परीक्षण स्पष्ट मूल्य दिखाते हैं क्योंकि सॉर्टिंग शफल और अस्थायी स्टोरेज जोड़ती है। यदि किसी हॉट पार्टिशन को प्रोसेस किया जाना चाहिए, तो मैं छोटे फाइल समूहों, आंशिक प्रगति, और सीमित संघर्ष पुनः प्रयासों का उपयोग करूंगा। मैं ओवरलैपिंग कॉम्पेक्शन को रोकूंगा।

200 GiB और 512 MiB पर, आदर्श आउटपुट लगभग 400 फाइलें हैं। एक पास लगभग 200 GiB पढ़ता है और 200 GiB लिखता है। इनपुट बाइट्स द्वारा 100 MiB/s की मापी गई एंड-टू-एंड दर पर, आदर्श रनटाइम 34.1 मिनट है; मैं 60 से 90 मिनट आरक्षित करूंगा और सिद्ध करूंगा कि दैनिक क्षमता दैनिक इनपुट से अधिक है।

कॉम्पेक्शन परमाणु रूप से (atomically) एक नया स्नैपशॉट कमिट करता है। मौजूदा क्वेरीज़ और सात-दिवसीय टाइम ट्रैवल पुरानी फाइलों का संदर्भ बनाए रखते हैं, इसलिए मैं कभी भी ऑब्जेक्ट्स को सीधे नहीं हटाऊंगा। नए स्नैपशॉट पर पंक्ति गणना, व्यावसायिक एग्रीगेट्स, बकेटेड चेकसम, और क्वेरी p95 को मान्य करने के बाद, मैं सात-दिवसीय नीति के तहत स्नैपशॉट समाप्त कर दूंगा। अनाथों की सफाई एक अलग, पहले-ड्राई-रन वाली, रूढ़िवादी रूप से विलंबित जॉब बनी रहेगी। रोलआउट डैशबोर्ड शुद्धता, नई छोटी-फाइल दर, फाइल पर्सेंटाइल, प्लानिंग p95, कॉम्पेक्शन लैग, संघर्ष और प्रति GiB लाभ को ट्रैक करेगा। कोई भी मुख्य रिग्रेशन विस्तार को रोक देगा।”

सामान्य गलतियाँ (Common Mistakes)

  • यह मान लेना कि उच्च फाइल संख्या कारण को सिद्ध करती है → ऐतिहासिक फाइलें वर्तमान क्वेरी फाइलें नहीं हैं → वर्तमान स्नैपशॉट की प्रोफाइलिंग करें और प्लानिंग को स्कैनिंग से अलग करें।
  • एक कॉम्पेक्शन चलाना और रुक जाना → माइक्रो-बैचेस, राइटर्स और बारीक पार्टिशन्स टुकड़े उत्पन्न करते रहते हैं → बैकलाग को साफ करने से पहले नए-टुकड़ों की दर को कम करें।
  • लक्ष्य आकार को एक कठिन गारंटी के रूप में मानना → एक राइटर केवल उन्हीं पंक्तियों को आउटपुट कर सकता है जो उसे प्राप्त होती हैं → लक्ष्य, बैच बाइट्स, वितरण और प्रति-पार्टिशन वॉल्यूम को एक साथ ट्यून करें।
  • पूरी 20 TiB टेबल को फिर से लिखना → लागत और संघर्ष का दायरा अत्यधिक हो जाता है → लाभ-सीमित बैचेस में कोल्ड पार्टिशन्स को प्रोसेस करें।
  • डिफ़ॉल्ट रूप से सॉर्ट या Z-ऑर्डर चुनना → दोनों शफल और अस्थायी स्टोरेज जोड़ते हैं → बिन पैकिंग से शुरुआत करें और प्रूनिंग बेंचमार्क के साथ क्लस्टरिंग को उचित ठहराएं।
  • पुरानी Parquet ऑब्जेक्ट्स को सीधे हटाना → बनाए रखे गए स्नैपशॉट और समवर्ती प्रश्न उन्हें संदर्भित कर सकते हैं → स्नैपशॉट समाप्ति और एक अलग ड्राई-रन अनाथ सफाई का उपयोग करें।
  • केवल कुल पंक्ति संख्या को मान्य करना → एक कमी और एक डुप्लिकेट एक-दूसरे को रद्द कर सकते हैं → व्यावसायिक एग्रीगेट्स, की काउंट्स, बकेटेड चेकसम और नमूने जोड़ें।
  • टिकाऊ थ्रूपुट के बिना रनटाइम का अनुमान लगाना → दैनिक इनपुट से कम दैनिक प्रोसेसिंग बैकलाग को बढ़ाती है → रीड, राइट, शफल, पुनः प्रयास और कॉम्पेक्शन लैग का बजट बनाएं।
  • coalesce(1) को एक सार्वभौमिक समाधान के रूप में उपयोग करना → एक राइटर पैरेललिज्म को नष्ट कर देता है और एक बॉटलनेक बनाता है → पार्टिशन वॉल्यूम और लक्ष्य बाइट्स से राइटर काउंट की गणना करें।

अनुवर्ती प्रश्न और उत्तर (Follow-Up Questions and Responses)

अनुवर्ती 1: 128 MiB के बजाय 512 MiB लक्ष्य का उपयोग क्यों करें?

512 MiB, या 536,870,912 बाइट्स का Iceberg डिफ़ॉल्ट लक्ष्य इस परिदृश्य में बड़ी टेबल के लिए एक प्रयोगात्मक प्रारंभिक बिंदु है, सार्वभौमिक इष्टतम नहीं। क्वेरी सेलेक्टिविटी, प्लानिंग लागत, टास्क पैरेललिज्म, कम्प्रेशन और प्रति-पार्टिशन दैनिक वॉल्यूम के विरुद्ध 128, 256, और 512 MiB या बड़े उम्मीदवारों का बेंचमार्क करें। अत्यधिक चयनात्मक क्वेरीज़ छोटी फाइलों को प्राथमिकता दे सकती हैं, जबकि थ्रूपुट स्कैन और बहुत बड़े पार्टिशन्स बड़ी फाइलों को प्राथमिकता दे सकते हैं।

अनुवर्ती 2: लक्ष्य बढ़ाने के बाद भी फाइलें केवल कुछ MiB की क्यों हैं?

लक्ष्य उस आउटपुट आकार का मार्गदर्शन करता है जिस तक पहुँचने का एक राइटर प्रयास करता है; यह विभिन्न कार्यों द्वारा रखे गए डेटा को मर्ज नहीं करता है। यदि एक-मिनट का बैच दर्जनों राइटर्स में विभाजित है, या एक राइटर कई कम-मात्रा वाले पार्टिशन्स को छूता है, तो टास्क कमिट होने पर फाइलें बंद हो जाती हैं। केवल लक्ष्य बढ़ाने के बजाय बैच आकार, राइट वितरण, पैरेललिज्म और पार्टिशन डिज़ाइन को बदलें।

अनुवर्ती 3: आप बिन पैकिंग, सॉर्टिंग और Z-ऑर्डरिंग के बीच कैसे चयन करते हैं?

बिन पैकिंग तब चुनें जब लक्ष्य कम फाइलें और कम ओपन ओवरहेड हो। सॉर्टिंग का परीक्षण तब करें जब क्वेरीज़ अक्सर एक कॉलम या एक पदानुक्रमित की (hierarchical key) पर फ़िल्टर करती हैं और फाइल स्टैटिस्टिक्स सीमाओं को प्रून कर सकते हैं। Z-ऑर्डरिंग का मूल्यांकन केवल तभी करें जब फ़िल्टर आमतौर पर कई आयामों के बदलते संयोजनों में फैले हों। दोनों बाद के बेंचमार्क में अतिरिक्त शफल, अस्थायी स्टोरेज, राइट प्रवर्धन (write amplification), और निरंतर रखरखाव शामिल करें।

अनुवर्ती 4: यदि कॉम्पेक्शन स्ट्रीमिंग राइट्स के साथ संघर्ष करता है तो क्या होगा?

पहले सक्रिय पार्टिशन्स को बाहर रखें। जब यह असंभव हो, तो छोटे फाइल समूहों का उपयोग करें, कॉनक्रेन्सी को सीमित करें, आंशिक प्रगति को सक्षम करें, और कमिट संघर्षों पर सीमित पुनः प्रयास लागू करें। शेड्यूलर को ओवरलैपिंग टेबल सीमाओं के लिए पारस्परिक अपवर्जन (mutual exclusion) लागू करना चाहिए। आंशिक प्रगति एक संघर्षरत समूह को पूर्ण पुनरारंभ (full rerun) के लिए बाध्य करने से रोकती है, लेकिन यह स्नैपशॉट और आंशिक-सफलता स्थिति जोड़ती है, इसलिए प्रत्येक समूह के परिणाम को रिकॉर्ड करें।

अनुवर्ती 5: कॉम्पेक्शन के तुरंत बाद ऑब्जेक्ट-स्टोर उपयोग कम क्यों नहीं होता है?

कॉम्पेक्शन एक ऐसा स्नैपशॉट कमिट करता है जो नई फाइलों को संदर्भित करता है। ऐतिहासिक स्नैपशॉट, ब्रांचेस, या टैग अभी भी समवर्ती रीड्स और टाइम ट्रैवल के लिए पुरानी फाइलों को संदर्भित करते हैं। सात-दिवसीय रिटेंशन संतुष्ट होने के बाद, स्नैपशॉट समाप्ति उन फाइलों को पुनः प्राप्त कर सकती है जिनकी बनाए रखे गए स्नैपशॉट को आवश्यकता नहीं है। किसी भी टेबल मेटाडेटा द्वारा संदर्भित नहीं की गई फाइलों के लिए एक अलग अनाथ-सफाई प्रक्रिया की आवश्यकता होती है।

अनुवर्ती 6: आप कैसे सिद्ध करते हैं कि लाभ कैशे या अतिरिक्त संसाधनों के बजाय कम छोटी फाइलों से हुआ है?

समान इंजन सेटिंग्स का उपयोग करें और कैशे स्थिति को लगातार कोल्ड या लगातार गर्म बनाएं। समान लॉजिकल स्नैपशॉट रेंज पर दोहराने योग्य क्वेरीज़ चलाएं और पहले और बाद में प्लानिंग समय, टास्क काउंट, फाइल ओपन, स्कैन किए गए बाइट्स और निष्पादन समय रिकॉर्ड करें। एक असम्पीडित (uncompacted), समान रूप से लोड किए गए पार्टिशन को एक नियंत्रण के रूप में रखें और कई रनों पर पर्सेंटाइल की तुलना करें। कार्य-कारण साक्ष्य केवल तभी मजबूत होता है जब फाइल लेआउट बदलता है और प्लानिंग या ओपन ओवरहेड इसके साथ लगातार गिरता है।

सार्वजनिक स्रोत

संबंधित प्रश्न