क्या आपका प्रोडक्शन डेटाबेस लगातार धीमा हो रहा है? जब किसी डेटाबेस में टेबल का साइज बहुत बड़ा हो जाता है, तो न केवल क्वेरी परफॉर्मेंस गिरती है, बल्कि बैकअप लेने और इंडेक्स को मेंटेन करने में भी भारी समय लगता है।
इस केस स्टडी में, हम एक वास्तविक जैसी स्थिति (realistic scenario) पर चर्चा करेंगे। हम देखेंगे कि कैसे एक तेजी से बढ़ते SaaS प्लेटफॉर्म 'BillEasy' ने अपने PostgreSQL डेटाबेस से 3 साल पुराने, लगभग 1 करोड़ (10 Million) इनवॉइस रिकॉर्ड्स को बिना किसी डाउनटाइम (Zero Downtime) के सफलतापूर्वक आर्काइव किया।
सिनेरियो: BillEasy की समस्या और चुनौती
'BillEasy' एक ऑनलाइन बिलिंग सॉफ्टवेयर है। पिछले 5 वर्षों में, उनके एक्टिव यूजर्स की संख्या तेजी से बढ़ी है। उनके प्राइमरी डेटाबेस में invoices नाम की एक मुख्य टेबल है, जिसमें कुल 5 करोड़ (50 Million) से अधिक रो (rows) हो चुके थे।
इस भारी डेटा के कारण उन्हें निम्नलिखित समस्याओं का सामना करना पड़ रहा था:
- क्वेरी स्पीड में गिरावट: सामान्य रिपोर्ट्स और डैशबोर्ड लोड होने में 5 से 8 सेकंड का समय लग रहा था।
- हाई मेमोरी यूसेज: इंडेक्स का साइज इतना बड़ा हो चुका था कि वह रैम (RAM) में फिट नहीं हो पा रहा था, जिससे डिस्क I/O बढ़ गया था।
- महंगा स्टोरेज: पुराना और निष्क्रिय डेटा भी महंगे, हाई-परफॉर्मेंस SSD स्टोरेज पर पड़ा हुआ था।
कंपनी को पिछले 3 साल से पुराने डेटा को डिलीट नहीं करना था (कानूनी नियमों के कारण), बल्कि उसे एक अलग 'Archive Database' में ट्रांसफर करना था, वह भी बिना लाइव एप्लीकेशन को रोके या डाउनटाइम लिए।
सीधा 'DELETE' क्वेरी चलाना खतरनाक क्यों था?
शुरुआत में, जूनियर डेवलपर ने एक सीधा सुझाव दिया:
DELETE FROM invoices WHERE created_at < '2021-01-01';अनुभवी डेटाबेस एडमिनिस्ट्रेटर (DBA) ने तुरंत इस सुझाव को खारिज कर दिया। इसके पीछे दो मुख्य कारण थे:
1. टेबल लॉकिंग (Table Locking)
जब आप एक ही क्वेरी में लाखों रोज़ को डिलीट करने का प्रयास करते हैं, तो डेटाबेस इंजन उस टेबल या उन रो पर 'Exclusive Lock' लगा देता है। इसका मतलब है कि जब तक यह डिलीट ऑपरेशन पूरा नहीं होगा, तब तक कोई भी नया यूजर नया इनवॉइस जेनरेट नहीं कर पाएगा। इससे एप्लीकेशन पूरी तरह ठप हो जाएगी।
2. ट्रांजैक्शन लॉग ब्लास्ट (Transaction Log Bloat)
एक साथ लाखों रिकॉर्ड्स डिलीट करने से डेटाबेस का Write-Ahead Log (WAL) या ट्रांजैक्शन लॉग बहुत बड़ा हो जाएगा, जिससे डिस्क स्पेस खत्म होने और डेटाबेस क्रैश होने का खतरा बढ़ जाता है।
समाधान: 4-स्टेप डेटा आर्काइविंग स्ट्रेटेजी
टीम ने बिना किसी डाउनटाइम के डेटा को आर्काइव करने के लिए एक सुरक्षित, बैच-बेस्ड (Batch-based) अप्रोच अपनाने का फैसला किया। आइए इस पूरी प्रक्रिया को स्टेप-बाय-स्टेप समझते हैं।
स्टेप 1: आर्काइव टेबल और डेस्टिनेशन डेटाबेस तैयार करना
सबसे पहले, टीम ने एक सस्ते क्लाउड स्टोरेज (Cold Storage) पर एक नया डेटाबेस सेटअप किया। इसके बाद, मुख्य डेटाबेस में एक आर्काइव टेबल बनाई गई जो बिल्कुल ओरिजिनल टेबल जैसी थी:
CREATE TABLE invoices_archive (LIKE invoices INCLUDING ALL);यह कमांड मूल टेबल के सभी कॉलम स्ट्रक्चर और डेटा टाइप्स को हूबहू नई टेबल में कॉपी कर देती है।
स्टेप 2: बैचिंग स्क्रिप्ट लिखना (The Chunking Approach)
एक साथ 1 करोड़ रोज़ को प्रोसेस करने के बजाय, टीम ने डेटा को 5,000 के छोटे-छोटे बैचेस में ट्रांसफर और डिलीट करने का निर्णय लिया। इसके लिए एक PL/pgSQL स्क्रिप्ट लिखी गई जो लूप में काम करती थी और हर बैच के बाद कुछ मिलीसेकंड का पॉज (Sleep) लेती थी, ताकि लाइव यूजर्स पर कोई असर न पड़े।
DO $$
DECLARE
rows_moved INT;
batch_limit INT := 5000;
BEGIN
LOOP
-- 1. डेटा को आर्काइव टेबल में कॉपी करें
INSERT INTO invoices_archive
SELECT * FROM invoices
WHERE created_at < '2021-01-01'
LIMIT batch_limit;
GET DIAGNOSTICS rows_moved = ROW_COUNT;
-- यदि कोई डेटा नहीं बचा, तो लूप से बाहर निकलें
IF rows_moved = 0 THEN
EXIT;
END IF;
-- 2. कॉपी किए गए डेटा को मुख्य टेबल से डिलीट करें
DELETE FROM invoices
WHERE id IN (SELECT id FROM invoices_archive);
-- 3. डेटाबेस को सांस लेने का मौका देने के लिए 1 सेकंड का पॉज लें
COMMIT;
PERFORM pg_sleep(1.0);
END LOOP;
END $$;इस स्क्रिप्ट की खूबसूरती यह है कि यह एक समय में केवल 5,000 रिकॉर्ड्स को ही लॉक करती है। 1 सेकंड का स्लीप टाइम (pg_sleep) डेटाबेस को अन्य लाइव ट्रांजैक्शन्स को प्रोसेस करने का पूरा मौका देता है।
स्टेप 3: डिस्क स्पेस खाली करना (Reclaiming Disk Space)
PostgreSQL और कई अन्य SQL डेटाबेस में, जब आप डेटा 'DELETE' करते हैं, तो वह डिस्क स्पेस तुरंत खाली नहीं होता। वह स्पेस 'Dead Tuples' के रूप में सुरक्षित रहता है।
इतने बड़े पैमाने पर डिलीट करने के बाद, खाली हुई डिस्क स्पेस को वापस पाने के लिए टीम ने pg_repack टूल का उपयोग किया। सामान्य VACUUM FULL कमांड टेबल को लॉक कर देती है, लेकिन pg_repack बिना टेबल को लॉक किए बैकग्राउंड में टेबल को री-ऑर्गेनाइज कर देता है और खाली स्पेस ऑपरेटिंग सिस्टम को वापस सौंप देता है।
स्टेप 4: एप्लीकेशन कोड को अपडेट करना
डेटा आर्काइव होने के बाद, एप्लीकेशन कोड में एक छोटा सा बदलाव किया गया। यदि कोई यूजर 3 साल से पुराना इनवॉइस ढूंढने की कोशिश करता है, तो एप्लीकेशन मुख्य टेबल के बजाय 'Archive Database' को क्वेरी करती है। इसके लिए कोड में एक सिंपल कंडीशनल राउटिंग लॉजिक लागू किया गया:
if (invoiceDate < threeYearsAgo) {
return queryArchiveDatabase(invoiceId);
} else {
return queryPrimaryDatabase(invoiceId);
}परिणाम और हासिल किए गए फायदे
यह पूरी प्रक्रिया बैकग्राउंड में लगभग 18 घंटे तक चली। इस दौरान 'BillEasy' के किसी भी यूजर को कोई धीमापन या एरर महसूस नहीं हुआ। परिणाम बेहद शानदार थे:
- डेटाबेस साइज में कमी: प्राइमरी डेटाबेस का साइज 450 GB से घटकर केवल 180 GB रह गया।
- क्वेरी परफॉर्मेंस बूस्ट: औसत क्वेरी रिस्पॉन्स टाइम 6 सेकंड से घटकर मात्र 120 मिलीसेकंड (ms) रह गया।
- लागत में बचत: पुराने डेटा को सस्ते कोल्ड स्टोरेज पर ले जाने से क्लाउड इंफ्रास्ट्रक्चर की लागत में 35% की कमी आई।
इस केस स्टडी से सीख और निष्कर्ष
बड़े डेटाबेस को मैनेज करना केवल बड़ी मशीनें (Scaling Up) खरीदने के बारे में नहीं है, बल्कि स्मार्ट डेटा लाइफसाइकिल मैनेजमेंट के बारे में है। जब भी आप बड़े पैमाने पर डेटा डिलीट या माइग्रेट करें, तो हमेशा छोटे बैचेस का उपयोग करें, ट्रांजैक्शन लॉक्स की निगरानी करें और लाइव ट्रैफिक को प्रभावित किए बिना काम पूरा करें।
अक्सर पूछे जाने वाले प्रश्न (FAQ)
1. क्या हम MySQL में भी इसी तरह बैचिंग कर सकते हैं?
हाँ, बिल्कुल। MySQL में आप स्टोर्ड प्रोसीजर (Stored Procedure) या किसी बाहरी स्क्रिप्ट (जैसे Python या Bash) का उपयोग करके LIMIT के साथ DELETE और INSERT ऑपरेशन्स को लूप में चला सकते हैं।
2. डेटा आर्काइव करने के लिए 5,000 का बैच साइज ही क्यों चुना गया?
यह एक संतुलित नंबर है। बहुत छोटा बैच (जैसे 100) प्रक्रिया को बहुत धीमा कर देगा, और बहुत बड़ा बैच (जैसे 1,00,000) डेटाबेस पर लॉक टाइम बढ़ा देगा। टेस्ट एनवायरनमेंट में रन करके आप अपने सर्वर के अनुसार बेस्ट बैच साइज चुन सकते हैं।
3. क्या आर्काइविंग के दौरान डेटा लॉस का खतरा होता है?
यदि आप ट्रांजैक्शनल ब्लॉक (BEGIN...COMMIT) का उपयोग करते हैं, तो खतरा नहीं होता। डेटा तभी मुख्य टेबल से डिलीट होना चाहिए जब वह आर्काइव टेबल में सफलतापूर्वक इंसर्ट हो चुका हो। सुरक्षा के लिए प्रोसेस शुरू करने से पहले फुल डेटाबेस बैकअप अवश्य लें।

0 Comments
You Can Contact on WhatsApp - 9509503477