यह पता लगाना कि क्यों एक प्रश्न जो विकास में अच्छा प्रदर्शन करता है और उत्पादन में परीक्षण करता है, कभी-कभी एक चुनौती हो सकती है। कुछ विशेषताओं के बारे में अधिक जानने के लिए पढ़ें, जो इस बारे में जानकारी प्रदान कर सकती हैं कि आपके प्रश्नों का उत्पादन में कैसा प्रदर्शन होता है।
वर्तमान में चल रही क्वेरी
जब कोई क्लाइंट PostgreSQL सर्वर को जोड़ता है, तो मुख्य पोस्टग्रेज सर्वर प्रक्रिया (ऐतिहासिक रूप से पोस्टमास्टर कहा जाता है) ) एक नई प्रक्रिया को जन्म देता है (जिसेबैकएंड . कहा जाता है ) ग्राहक के प्रश्नों की सेवा के लिए। इसलिए, प्रत्येक बैकएंड या तो अपने क्लाइंट द्वारा एक क्वेरी भेजने की प्रतीक्षा कर रहा है, या एक को निष्पादित करने का प्रयास कर रहा है।
सिस्टम दृश्य pg_stat_activity वर्तमान में चल रहे प्रत्येक बैकएंड के बारे में जानकारी दिखाता है। विशेष रूप से, यह उस क्वेरी को दिखाता है जिसे बैकएंडिस वर्तमान में सक्रिय होने पर निष्पादित कर रहा है, या अंतिम क्वेरी इसे निष्पादित करता है यदि यह क्लाइंट को किसी अन्य क्वेरी में भेजने की प्रतीक्षा कर रहा है।
यहां दो बैकएंड हैं जो डेटाबेस से जुड़े क्लाइंट की सेवा कर रहे हैं testdb
, दोनों सक्रिय रूप से अपने प्रश्नों को क्रियान्वित कर रहे हैं:
testdb=# select usename,datname,state,query from pg_stat_activity where datname='testdb';
-[ RECORD 1 ]-----------------------------------------------------------------------------
usename | postgres
datname | testdb
state | active
query | SELECT pg_sleep(10);
-[ RECORD 2 ]-----------------------------------------------------------------------------
usename | postgres
datname | testdb
state | active
query | select usename,datname,state,query from pg_stat_activity where datname='testdb';
कभी-कभी क्वेरी लॉक की प्रतीक्षा कर रही होती है, और यह भी inpg_stat_activity दिखाता है। आप एक INSERT को एक रिलेशन लॉक की प्रतीक्षा करते हुए यहाँ देख सकते हैं:
testdb=# select wait_event_type, wait_event, left(query, 60) from pg_stat_activity where datname='testdb';
-[ RECORD 1 ]---+-------------------------------------------------------------
wait_event_type | Client
wait_event | ClientRead
left | lock table t in access exclusive mode;
-[ RECORD 2 ]---+-------------------------------------------------------------
wait_event_type |
wait_event |
left | select wait_event_type, wait_event, left(query, 60) from pg_
-[ RECORD 3 ]---+-------------------------------------------------------------
wait_event_type | Lock
wait_event | relation
left | insert into t values (1);
pg_stat_activity पर अधिक जानकारी के लिए, दस्तावेज़ देखें।
हालांकि यह दृश्य यह समझने में मददगार है कि पोस्टग्रेज़ वर्तमान में क्या कर रहा है, यह क्वेरी निष्पादन आंकड़ों के बारे में जानकारी या निष्पादन समाप्त करने वाले प्रश्नों के बारे में जानकारी प्रदान नहीं करता है।
सभी क्वेरीज़ अतीत में चलती हैं
उसके लिए, एक्सटेंशन pg_stat_statements अमूल्य है। यह एक्सटेंशन कोर पोस्टग्रेएसक्यूएल वितरण में शामिल है और एडब्ल्यूएस आरडीएस और जीसीपी एसक्यूएल जैसी प्रबंधित सेवाओं पर भी उपलब्ध है।
pg_stat_statements (PSS) PostgreSQL शब्दों में एक "एक्सटेंशन" है, और इसे पहले स्थापित करने की आवश्यकता है:
- यह देखने के लिए कि क्या एक्सटेंशन पूर्व-स्थापित है या इसके लिए किसी अन्य पैकेज की स्थापना की आवश्यकता है, अपने Linux डिस्ट्रो दस्तावेज़ से परामर्श करें। उदाहरण के लिए, Centos 7 पर आपको
sudo yum install postgresql-contrib
करना होगा। । - मुख्य कॉन्फ़िगरेशन फ़ाइल को संपादित करें postgresql.conf (आमतौर पर
/etc
के अंतर्गत) , जैसे/etc/postgresql/10/main/postgresql.conf
डेबियन पर) औरshared_preload_libraries
. का मान बदलें "pg_stat_statements" के लिए। यह मानों की अल्पविराम से अलग की गई सूची है, इसलिए यदि वहां पहले से कुछ है, तो अल्पविराम लगाएं और फिर "pg_stat_statements"। - AWS RDS के लिए, आपको अपने सक्रिय पैरामीटर समूह को संशोधित करना होगा और मान सेट करना होगा।
- “shared_preload_libraries” को संपादित करने के बाद, आपको PostgreSQL डेमॉन को पुनरारंभ करना होगा। दुर्भाग्य से इसके आसपास कोई रास्ता नहीं है। एडब्ल्यूएस आरडीएस पर, आपको आरडीएस इंस्टेंस को फिर से शुरू करना होगा।
- पुनरारंभ करने के बाद, PostgreSQL सर्वर ने साझा लाइब्रेरी को लोड किया होगा, और हम
CREATE EXTENSION pg_stat_statements
चलाकर एक्सटेंशन इंस्टॉल कर सकते हैं . इस कमांड को चलाने के लिए आपको एक सुपरयूजर होना होगा। - आप वास्तव में किसी भी डेटाबेस में एक्सटेंशन इंस्टॉल कर सकते हैं, और फिर भी सभी डेटाबेस में क्वेरीज़ देख सकते हैं।
एक बार एक्सटेंशन इंस्टॉल हो जाने पर, आप pg_stat_statements
. नाम के व्यू को क्वेरी कर सकते हैं एक्सटेंशन इंस्टॉल होने के बाद से निष्पादित प्रत्येक क्वेरी के बारे में जानकारी प्राप्त करने के लिए।
संख्याएं, जैसे कि क्वेरी को निष्पादित करने में लगने वाला समय, योग के रूप में जमा किया जाता है। केवल क्वेरी निष्पादन समय के लिए, कुछ आँकड़े (औसत, न्यूनतम, अधिकतम, मानक विचलन) प्रस्तुत किए जाते हैं। इन मानों को फ़ंक्शन का उपयोग करके साफ़ किया जा सकता हैpg_stat_statements_reset
।
यहां बताया गया है कि pg_stat_statements
. से एक पंक्ति कैसी है ऐसा दिखता है:
testdb=# select * from pg_stat_statements where query like '%pg_sleep%' and dbid=42548;
-[ RECORD 1 ]-------+--------------------
userid | 10
dbid | 42548
queryid | 2649515222348904837
query | SELECT pg_sleep($1)
calls | 1
total_time | 10016.782625
min_time | 10016.782625
max_time | 10016.782625
mean_time | 10016.782625
stddev_time | 0
rows | 1
shared_blks_hit | 0
shared_blks_read | 0
shared_blks_dirtied | 0
shared_blks_written | 0
local_blks_hit | 0
local_blks_read | 0
local_blks_dirtied | 0
local_blks_written | 0
temp_blks_read | 0
temp_blks_written | 0
blk_read_time | 0
blk_write_time | 0
पहचान करने वाले पैरामीटर (उपयोगकर्ता, डेटाबेस, क्वेरी) के अलावा, आप अपनी क्वेरी के बारे में कई दिलचस्प बातें समझ सकते हैं:
- आम तौर पर निष्पादित होने में कितना समय लगता है (
mean_time
) - यह औसतन कितनी पंक्तियाँ लौटाता है (
rows
/calls
) - साझा बफ़र कैश से पढ़े जाने वाले डेटा की मात्रा, और डिस्क से पढ़े जाने वाले डेटा की मात्रा (
shared_blks_read
क्वेरी द्वारा पढ़े जाने वाले डेटा की कुल मात्रा को दिखाता है, जिसमें सेshared_blks_hit
कैश से आया) - कैश दबाव (
shared_blks_written
के कारण डेटा की मात्रा जिसे डिस्क पर सिंक्रोनस रूप से लिखा जाना था। ) - लिखे गए डेटा की मात्रा, स्पर्श किए गए ब्लॉकों की संख्या के रूप में (
shared_blks_dirtied
) - डिस्क में बिताया गया समय पढ़ता और लिखता है (
blk_{read,write}_time
) - अस्थायी फ़ाइलें लिखी और पढ़ी गईं (
temp_blks_{read,written}
) - अस्थायी तालिकाओं को लिखा और पढ़ा गया (
local_*
)
डिस्क पढ़ने और लिखने का समय केवल तभी उपलब्ध होता है जब कॉन्फ़िगरेशन पैरामीटरtrack_io_timing
चालू है। डिफ़ॉल्ट रूप से, यह नहीं है। अधिकांश आधुनिक लिनक्स सिस्टम पर इस पैरामीटर को चालू करना ठीक होना चाहिए। और पढ़ें।
pg_stat_statements
का स्नैपशॉट लेना उपयोगी है डेटा लगातार नियमित अंतराल पर यह देखने के लिए कि ये पैरामीटर प्रति-क्वेरी के आधार पर कैसे चलन में हैं। ओपन सोर्स टूल pgmetrics pg_stat_statements
को निकाल और उजागर कर सकता है आसान स्वचालन के लिए JSON के रूप में डेटा।
क्वेरी एक समय सीमा के दौरान चलती हैं
एक बार जब आपके पास ऐसी प्रणाली हो जाती है तो एक निश्चित समय सीमा में निष्पादित प्रश्नों को ट्रैक करना आसान हो जाता है। इससे समस्याओं को डीबग करना आसान हो जाता है, जैसे कि रात्रिकालीन बैच की नौकरी में अपेक्षा से अधिक समय क्यों लगा।
दो दिए गए टाइमस्टैम्प के बीच काउंटरों को घटाकर, आप न्यूनतम, अधिकतम और मानक विचलन को छोड़कर, पहले की तरह सबसे अधिक संख्याएं ढूंढ सकते हैं। यह उन प्रश्नों की पहचान करने के लिए पर्याप्त है जो समय सीमा के भीतर निष्पादित किए गए थे और उनके द्वारा उपभोग किए गए संसाधनों की पहचान करने के लिए पर्याप्त है।
धीमी क्वेरी लॉग करना
अपेक्षा से अधिक समय लेने वाले प्रश्नों को शीघ्रता से पहचानने का एक अन्य तरीका बयानों की लॉगिंग चालू करना है। आप एक थ्रेशोल्ड अवधि निर्दिष्ट कर सकते हैं, और यदि क्वेरी को समाप्त होने में इससे अधिक समय लगता है, तो इसे लॉग किया जाता है। (नियमित PostgreSQL लॉग फ़ाइल में, धीमी क्वेरी के लिए कोई अलग नहीं है।)
इस सुविधा को चालू करने के लिए, कॉन्फ़िगरेशन को नीचे दिए अनुसार संपादित करें:
log_min_duration_statement = 1000 # in milliseconds
और पोस्टग्रेज को पुनः लोड करें। आप ALTER SYSTEM
. का भी उपयोग कर सकते हैं :
ALTER SYSTEM SET log_min_duration_statement = 1000; -- in milliseconds
इसके साथ, कोई भी स्टेटमेंट (गैर-डीएमएल सहित) जो खत्म होने में एक सेकंड से अधिक समय लेता है, लॉग हो जाता है:
2019-12-02 16:57:05.727 UTC [8040] postgres@testdb LOG: duration: 10017.862 ms statement: SELECT pg_sleep(10);
क्वेरी द्वारा लिया गया वास्तविक समय, साथ ही पूर्ण SQL पाठ, लॉग किया जाता है।
यदि आपके पास लॉग मॉनिटरिंग सिस्टम है और प्रति घंटे / प्रति दिन धीमी क्वेरी की संख्या को ट्रैक कर सकता है, तो यह एप्लिकेशन प्रदर्शन के एक अच्छे संकेतक के रूप में काम कर सकता है।
क्वेरी निष्पादन योजनाएं
एक बार जब आप एक क्वेरी ढूंढ लेते हैं जो आपको लगता है कि तेजी से चलना चाहिए, तो अगला कदम इसकी क्वेरी योजना पर एक नज़र डालना है। आम तौर पर, आपको काम करने के लिए उत्पादन सर्वर से वास्तविक क्वेरी योजना की आवश्यकता होती है। यदि आप EXPLAIN को उत्पादन सर्वर पर चलाने में सक्षम हैं, तो आपको auto_explain
पर भरोसा करने की आवश्यकता है ।
auto_explain
एक और कोर पोस्टग्रेएसक्यूएल एक्सटेंशन है, जो या तो पहले से इंस्टॉल है या आपके डिस्ट्रो के लिए "कंट्रीब" पैकेज के रूप में उपलब्ध है। यह AWSRDS पर भी उपलब्ध है। auto_explain
pg_stat_statements
. की तुलना में इंस्टॉल करना थोड़ा आसान है :
- पोस्टग्रेज कॉन्फ़िगरेशन (या RDS पैरामीटर समूह) को संपादित करें
shared_preload_libraries
auto_explain
include शामिल करने के लिए । - आपको Postgres को पुनरारंभ करने की आवश्यकता नहीं है, हालांकि, आप इसके बजाय बस चला सकते हैं:
LOAD 'auto_explain';
। - आप इसकी सेटिंग कॉन्फ़िगर करना चाहेंगे, कम से कम यह एक:
auto_explain.log_min_duration = 1000 # seconds
अनिवार्य रूप से, जब भी कोई क्वेरीauto_explain.log_min_duration
. से अधिक समय लेती है पूरा करने के लिए सेकंड की संख्या, auto_explain लॉग फ़ाइल में क्वेरी और उसकी क्वेरी निष्पादन योजना को इस तरह से लॉग करता है:
2019-12-04 09:23:05.130 UTC [12823] postgres@testdb LOG: duration: 11025.765 ms plan:
Query Text: select pg_sleep(11);
Result (cost=0.00..0.01 rows=1 width=4) (actual time=11025.716..11025.718 rows=1 loops=1)
Output: pg_sleep('11'::double precision)
यह JSON प्रारूप में भी योजना को लॉग कर सकता है, यदि आपके पास ऐसी स्क्रिप्ट हैं जो इसे संसाधित कर सकती हैं:
2019-12-02 17:30:53.676 UTC [8040] postgres@testdb LOG: duration: 10000.230 ms plan:
{
"Query Text": "SELECT pg_sleep(10);",
"Plan": {
"Node Type": "Result",
"Parallel Aware": false,
"Startup Cost": 0.00,
"Total Cost": 0.01,
"Plan Rows": 1,
"Plan Width": 4,
"Actual Startup Time": 10000.205,
"Actual Total Time": 10000.206,
"Actual Rows": 1,
"Actual Loops": 1,
"Output": ["pg_sleep('10'::double precision)"],
"Shared Hit Blocks": 0,
"Shared Read Blocks": 0,
"Shared Dirtied Blocks": 0,
"Shared Written Blocks": 0,
"Local Hit Blocks": 0,
"Local Read Blocks": 0,
"Local Dirtied Blocks": 0,
"Local Written Blocks": 0,
"Temp Read Blocks": 0,
"Temp Written Blocks": 0,
"I/O Read Time": 0.000,
"I/O Write Time": 0.000
},
"Triggers": [
]
}
पोस्टग्रेज में, पहले से निष्पादित एक क्वेरी के निष्पादन योजना को देखने के लिए auto_explain के अलावा कोई रास्ता नहीं है, जो auto_explain को आपके टूलबॉक्स में एक महत्वपूर्ण टूल बनाता है।