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

यदि आप PostgreSQL चला रहे हैं और इसकी मेमोरी का उपयोग ऑप्टिमाइज़ करना चाहते हैं, तो यहां कुछ महत्वपूर्ण सेटिंग्स हैं जिन पर ध्यान देना चाहिए।

ट्यून करने के लिए मुख्य मेमोरी सेटिंग्स

आइए सबसे महत्वपूर्ण PostgreSQL मेमोरी सेटिंग्स को तोड़ते हैं जिन्हें आपको समायोजित करने पर विचार करना चाहिए।

  1. shared_buffers

shared_buffers को PostgreSQL की व्यक्तिगत मेमोरी स्टैश के रूप में सोचें जहाँ यह अक्सर एक्सेस किए गए डेटा को रखता है। विचार यह है कि आपके डेटा का अधिकतम हिस्सा मेमोरी में रखा जाए ताकि महंगे डिस्क रीड को कम किया जा सके।

सिफारिश की गई सेटिंग:

अधिकांश विशेषज्ञ इसको आपके सिस्टम की कुल RAM का लगभग 25% सेट करने की सलाह देते हैं।

उदाहरण के लिए, यदि आपके पास 16GB RAM है, तो इसे लगभग 4GB पर सेट करना एक अच्छा प्रारंभिक बिंदु है।

  1. work_mem

जब भी PostgreSQL क्वेरी को प्रोसेस करता है जिसमें डेटा को सॉर्ट करना, जोड़ना या समूह बनाना शामिल होता है, यह work_mem का उपयोग करता है। यह सेटिंग नियंत्रित करती है कि प्रत्येक ऑपरेशन को कितनी मेमोरी मिलती है इससे पहले कि वह अस्थायी फ़ाइलों को डिस्क पर लिखना शुरू करे।

उदाहरण:

  • यदि work_mem = 50MB है और आपकी क्वेरी में 5 सॉर्टिंग कार्य हैं, तो यह 50MB x 5 = 250MB मेमोरी का उपयोग कर सकता है।
  • अब कल्पना करें कि 10 उपयोगकर्ता समान क्वेरियाँ चला रहे हैं - इसका मतलब है कि 250MB x 10 = 2.5GB मेमोरी का उपयोग हो रहा है।

टिप:

  • यदि इसे बहुत कम सेट करें, तो क्वेरियाँ डिस्क उपयोग के कारण धीमी हो सकती हैं।
  • यदि इसे बहुत अधिक सेट करें, तो आप तेजी से मेमोरी खत्म कर सकते हैं, खासकर जब कई उपयोगकर्ता हों।

कभी-कभी, बड़े work_mem मान वास्तव में चीजों को धीमा कर सकते हैं क्योंकि PostgreSQL को बड़े मेमोरी हिस्सों को प्रबंधित करना पड़ता है।

  1. effective_cache_size

यह सेटिंग थोड़ी अलग है - यह वास्तव में मेमोरी आवंटित नहीं करती है बल्कि PostgreSQL को बताती है कि इसे OS कैश से कितनी मेमोरी लगती है कि यह उपयोग कर सकता है। PostgreSQL इस मान का उपयोग यह तय करने के लिए करता है कि इसे इंडेक्स का उपयोग करना चाहिए या अनुक्रमिक स्कैन करना चाहिए।

गलत सेट करना:

  • बहुत कम? PostgreSQL इंडेक्स से बच सकता है, यह सोचकर कि मेमोरी कम है।
  • बहुत अधिक? PostgreSQL बहुत आशावादी हो सकता है और गलत निर्णय ले सकता है।

एक अच्छा नियम: इसे 50-75% आपके कुल RAM पर सेट करें, खासकर यदि PostgreSQL मशीन पर मुख्य कार्यभार है।

  1. maintenance_work_mem

यह सेटिंग इस बारे में है कि PostgreSQL VACUUM, CREATE INDEX, और अन्य रखरखाव कार्यों के लिए कितनी मेमोरी का उपयोग कर सकता है। इस मान को अधिक सेट करने से इन ऑपरेशनों को तेज़ी से किया जा सकता है बिना सामान्य डेटाबेस गतिविधि को धीमा किए।

सुझाई गई सेटिंग:

यदि आपके पास जगह है, तो इसे 1GB या अधिक पर बढ़ा दें ताकि रखरखाव कार्य तेजी से हो सकें।

मेमोरी सेटिंग्स को संशोधित करने के तरीके

PostgreSQL मेमोरी सेटिंग्स को आपके आवश्यकताओं और जोखिम सहिष्णुता के आधार पर कई तरीकों से संशोधित करने की अनुमति देता है। यहाँ सबसे प्रभावी दृष्टिकोण हैं:

  1. ग्लोबली मेमोरी सेटिंग्स को संशोधित करना

सभी सत्रों और क्वेरियों में स्थायी परिवर्तनों के लिए, PostgreSQL कॉन्फ़िगरेशन फ़ाइल (postgresql.conf) को संशोधित करें या ALTER SYSTEM का उपयोग करें:


ALTER SYSTEM SET work_mem = '500MB';
ALTER SYSTEM SET shared_buffers = '8GB';
ALTER SYSTEM SET effective_cache_size = '20GB';
SELECT pg_reload_conf();  -- बिना पुनरारंभ किए परिवर्तनों को लागू करें
  1. प्रत्येक सत्र के अनुसार सेटिंग्स बदलना

अस्थायी समायोजनों के लिए जो केवल वर्तमान कनेक्शन को प्रभावित करते हैं:

SET work_mem = '100MB';
SET effective_cache_size = '16GB';

मेरी PostgreSQL मेमोरी ट्यूनिंग का असली उदाहरण

परिदृश्य ##o

एक PostgreSQL 10 डेटाबेस जो 30GB RAM सर्वर पर चल रहा है, जिसमें अक्सर 15GB RAM उपलब्ध है, वित्तीय लेनदेन को प्रोसेस करते समय धीमी CSV निर्यात क्वेरी प्रदर्शन का अनुभव कर रहा था। चार बड़े तालिकाओं को जोड़ने वाली एक जटिल क्वेरी परिणाम उत्पन्न करने में 33 सेकंड ले रही थी:


SELECT * FROM finance_transaction ft
INNER JOIN billing_record br ON br.id = ft.billing_record
INNER JOIN transaction_log tl ON ft.transaction_log = tl.id
INNER JOIN transaction_audit_history tah ON tah.finance_transaction = ft.id;

तालिका के आकार:

  • finance_transaction (~1 मिलियन पंक्तियाँ)
  • transaction_log (~1 मिलियन पंक्तियाँ)
  • transaction_audit_history (~4 मिलियन पंक्तियाँ)
  • billing_record (~1 मिलियन पंक्तियाँ)

डिफ़ॉल्ट मेमोरी सेटिंग्स:

सेटिंग्सडिफ़ॉल्ट मान
shared_buffers128MB
work_mem4MB
maintenance_work_mem64MB
effective_cache_size4GB

क्वेरी निष्पादन योजना (EXPLAIN ANALYZE)

Gather  (cost=1071962.33..3055242.09 rows=6022483 width=4782) (actual time=26603.645..33465.648 rows=4847517 loops=1)
  Workers Planned: 4
  Workers Launched: 4
  ->  Hash Join  (cost=1070962.33..2451993.79 rows=1505621 width=4782) (actual time=26817.703..29038.177 rows=969503 loops=5)
        Hash Cond: (ft.id = tah.finance_transaction)
        ->  Hash Join  (cost=716707.62..1254298.44 rows=403544 width=4591) (actual time=18471.362..19081.998 rows=259931 loops=5)
              Hash Cond: (br.id = ft.billing_record)
              ->  Parallel Seq Scan on billing_record br  (cost=0.00..39488.92 rows=335492 width=3598) (actual time=0.005..42.297 rows=268393 loops=5)
              ->  Hash  (cost=501594.96..501594.96 rows=1564453 width=993) (actual time=18468.587..18468.589 rows=1299656 loops=5)
                    Buckets: 4096  Batches: 512  Memory Usage: 708kB
                    ->  Hash Join  (cost=103452.20..501594.96 rows=1564453 width=993) (actual time=9094.933..15042.241 rows=1300948 loops=5)
                          Hash Cond: (tl.id = ft.transaction_log)
                          ->  Seq Scan on transaction_log tl  (cost=0.00..33484.53 rows=1564453 width=766) (actual time=0.019..133.507 rows=1564453 loops=5)
                          ->  Hash  (cost=46549.31..46549.31 rows=1300631 width=227) (actual time=9092.767..9092.768 rows=1300948 loops=5)
                                Buckets: 16384  Batches: 128  Memory Usage: 2199kB
                                ->  Seq Scan on finance_transaction ft  (cost=0.00..46549.31 rows=1300631 width=227) (actual time=0.005..143.568 rows=1300948 loops=5)
        ->  Hash  (cost=165645.54..165645.54 rows=4852654 width=191) (actual time=8267.360..8267.360 rows=4852654 loops=5)
              Buckets: 32768  Batches: 512  Memory Usage: 2059kB
              ->  Seq Scan on transaction_audit_history tah  (cost=0.00..165645.54 rows=4852654 width=191) (actual time=0.020..789.242 rows=4852654 loops=5)
Planning time: 0.346 ms
Execution time: 33586.541 ms

क्वेरी निष्पादन योजना का विश्लेषण करें:

समस्याEXPLAIN ANALYZE से अवलोकनसंभावित कारणहल
हैश जोइन्स में डिस्क स्पिलBuckets: 4096 → Batches: 512 Memory Usage: 708kBwork_mem बहुत कम है (डिफ़ॉल्ट 4MB)work_mem को 300MB बढ़ाएँ ALTER SYSTEM SET work_mem = '300MB';
अनुक्रमिक स्कैन से उच्च I/Obilling_record, finance_transaction, और transaction_log पर समानांतर अनुक्रम स्कैनshared_buffers बहुत कम है (डिफ़ॉल्ट 128MB)shared_buffers को 8GB बढ़ाएँ ALTER SYSTEM SET shared_buffers = '8GB';
क्वेरी प्लानर उपलब्ध RAM का कम आकलन करता हैयह इंडेक्स स्कैन के बजाय अधिक अनुक्रमिक स्कैन का उपयोग करता हैeffective_cache_size बहुत कम है (डिफ़ॉल्ट 4GB)effective_cache_size को 20GB बढ़ाएँ ALTER SYSTEM SET effective_cache_size = '20GB';

मेमोरी सेटिंग्स बढ़ाने के बाद, यह EXPLAIN ANALYZE परिणाम है:

Gather  (cost=1071962.33..3055242.09 rows=6022483 width=4782) (actual time=16228.246..23884.145 rows=4847517 loops=1)
  Workers Planned: 4
  Workers Launched: 4
  ->  Hash Join  (cost=1070962.33..2451993.79 rows=1505621 width=4782) (actual time=17226.338..20072.376 rows=969503 loops=5)
        Hash Cond: (ft.id = tah.finance_transaction)
        ->  Hash Join  (cost=716707.62..1254298.44 rows=403544 width=4591) (actual time=14289.482..15561.150 rows=259931 loops=5)
              Hash Cond: (br.id = ft.billing_record)
              ->  Parallel Seq Scan on billing_record br  (cost=0.00..39488.92 rows=335492 width=3598) (actual time=0.005..37.096 rows=268393 loops=5)
              ->  Hash  (cost=501594.96..501594.96 rows=1564453 width=993) (actual time=14287.210..14287.212 rows=1299656 loops=5)
                    Buckets: 524288  Batches: 8  Memory Usage: 46914kB
                    ->  Hash Join  (cost=103452.20..501594.96 rows=1564453 width=993) (actual time=3728.706..6986.704 rows=1300948 loops=5)
                          Hash Cond: (tl.id = ft.transaction_log)
                          ->  Seq Scan on transaction_log tl  (cost=0.00..33484.53 rows=1564453 width=766) (actual time=0.018..123.814 rows=1564453 loops=5)
                          ->  Hash  (cost=46549.31..46549.31 rows=1300631 width=227) (actual time=3704.309..3704.309 rows=1300948 loops=5)
                                Buckets: 2097152  Batches: 2  Memory Usage: 151889kB
                                ->  Seq Scan on finance_transaction ft  (cost=0.00..46549.31 rows=1300631 width=227) (actual time=0.018..139.211 rows=1300948 loops=5)
        ->  Hash  (cost=165645.54..165645.54 rows=4852654 width=191) (actual time=2927.466..2927.466 rows=4852654 loops=5)
              Buckets: 2097152  Batches: 4  Memory Usage: 246002kB
              ->  Seq Scan on transaction_audit_history tah  (cost=0.00..165645.54 rows=4852654 width=191) (actual time=0.025..630.852 rows=4852654 loops=5)
Planning time: 0.341 ms
Execution time: 24013.565 ms

प्रदर्शन तुलना: मेमोरी सेटिंग्स बढ़ाने से पहले बनाम बाद में

मैट्रिकपहले (डिफ़ॉल्ट सेटिंग्स)बाद में (ऑप्टिमाइज्ड मेमोरी सेटिंग्स)सुधार
कुल निष्पादन समय33.58s24.01s⬇ ~28.5% तेज (~9.5s बचत)
हैश जोइन (ft.id = tah.finance_transaction)29.03s20.07s⬇ ~9s तेज
हैश जोइन (br.id = ft.billing_record)19.08s15.56s⬇ ~3.5s तेज
हैश बैच (ft.transaction_log)128 बैच2 बैच✅ डिस्क स्पिल में भारी कमी
हैश बैच (transaction_audit_history)512 बैच4 बैच✅ डिस्क उपयोग में कमी

सही मेमोरी सेटिंग्स चुनना: एक केस-बाय-केस दृष्टिकोण

PostgreSQL मेमोरी सेटिंग्स को ट्यून करना कोई एक-आकार-फिट-सब समाधान नहीं है। यह आपके डेटाबेस के आकार, समवर्ती उपयोगकर्ताओं, और क्वेरी पैटर्न पर निर्भर करता है। सही work_mem, shared_buffers, और effective_cache_size खोजें।

  • यदि आपके सर्वर में बहुत सारी फ्री RAM है, तो आप PostgreSQL को अधिक मेमोरी आवंटित कर सकते हैं।
  • यदि आपके पास बहुत से समवर्ती उपयोगकर्ता हैं, तो प्रति क्वेरी बहुत अधिक मेमोरी आवंटित करना सिस्टम अस्थिरता का कारण बन सकता है
  • धीमी क्वेरियों पर EXPLAIN ANALYZE चलाएँ ताकि डिस्क स्पिल और हैश जोइन की अक्षमताओं की पहचान की जा सके।

यदि आप सुरक्षित रूप से परिवर्तन का परीक्षण करना चाहते हैं बिना पूरे सिस्टम को प्रभावित किए, तो ग्लोबली के बजाय प्रति क्वेरी सेटिंग्स लागू करें:

✅ एक भारी क्वेरी के लिए सेटिंग्स बदलें:

SET LOCAL work_mem = '300MB';
SELECT * FROM finance_transaction ft
INNER JOIN billing_record br ON br.id = ft.billing_record
INNER JOIN transaction_log tl ON ft.transaction_log = tl.id
INNER JOIN transaction_audit_history tah ON tah.finance_transaction = ft.id;

निष्कर्ष

PostgreSQL मेमोरी सेटिंग्स को ट्यून करना प्रदर्शन में एक बड़ा अंतर ला सकता है, आपकी क्वेरियों को तेज़ी से चलाने में मदद करता है और अनावश्यक डिस्क I/O को कम करता है। कुंजी यह है कि आपके डेटाबेस लोड, उपलब्ध RAM, और आपकी क्वेरियों के व्यवहार के आधार पर सही संतुलन खोजें।

मुख्य बातें:

  • अपने कार्यभार को जानें – मेमोरी सेटिंग्स को अंधाधुंध बढ़ाने से बचें; पहले यह विश्लेषण करें कि आपकी क्वेरियाँ कैसे चल रही हैं।
  • उपयोग करें EXPLAIN ANALYZE – यह आपको डिस्क स्पिल और अक्षमताओं को पहचानने में मदद करेगा।
  • ध्यान से work_mem को समायोजित करें – एक उच्च मान जोड़ों और सॉर्टिंग को तेज़ कर सकता है, लेकिन इसे बहुत अधिक सेट करने से आपकी सभी RAM खत्म हो सकती है।
  • सही स्तर पर सेटिंग्स बदलें – समग्र सुधार के लिए ग्लोबल सेटिंग्स का उपयोग करें, अस्थायी समायोजनों के लिए सत्र सेटिंग्स, और वास्तव में भारी ऑपरेशनों के लिए प्रति-क्वेरी सेटिंग्स।
  • प्रभाव की निगरानी करें – लॉग की जाँच करें, प्रदर्शन को ट्रैक करें, और आवश्यकतानुसार समायोजित करें।

दिन के अंत में, PostgreSQL ट्यूनिंग एक विज्ञान और प्रयोग का हिस्सा है। छोटे से शुरू करें, परिणामों को ट्रैक करें, और चलते-चलते समायोजित करें। सही सेटिंग्स के साथ, आपका डेटाबेस अधिक सुचारू, तेज़, और बहुत अधिक कुशलता से चलेगा। 🚀