VPN वरून psql वेळेचे मापन: नेटवर्कची प्रतीक्षा क्वेरीच्या कामापासून वेगळी करणे
psql प्रत्येक विधानासाठी एकच उलटलेला वेळ सांगतो, त्यामुळे संथ VPN तो फुगवतो. कोणतीही बाजू ट्यून करण्यापूर्वी कनेक्ट, अंमलबजावणी, हस्तांतरण आणि येणे-जाणे हा वेळ वेगळा करा.
तुमचा अहवाल डेटाबेस होस्टवर सुमारे एका सेकंदात आणि VPN वरून चारमध्ये पूर्ण होतो, आणि psql जी संख्या छापतो ती सरळ डेटाबेसकडे बोट दाखवते। ती संख्या क्लायंट बाजूची स्टॉपवॉच आहे, सर्व्हरचे मोजमाप नाही। ती विधानाचा बाहेर जाण्याचा मार्ग, उत्तराची प्रतीक्षा आणि परत येणाऱ्या ओळी या सर्वांचा समावेश करते। या तिन्ही वेगळ्या करणे हाच कोणती बाजू ट्यून करायची हे जाणून घेण्याचा एकमेव मार्ग।
psql टाइमर प्रत्यक्षात काय मोजतो
\timing on क्लायंट विधान सॉकेटमध्ये लिहिण्याच्या थोड्या आधी स्टॉपवॉच सुरू करतो आणि त्या निकालाची शेवटची ओळ वाचली गेल्यावर थांबवतो। सर्व्हरची स्वतःची अंमलबजावणी त्या खिडकीत कुठेतरी असते, आणि पॅकेट्स टनेलमध्ये घालवतात तो प्रत्येक मिलिसेकंदही। आउटपुटमध्ये काहीही त्यांना वेगळे करत नाही। EXPLAIN देखील संख्या छापतो, पण ती सर्व्हर तयार करतो आणि क्लायंटची प्रतीक्षा वगळतो। दोन संख्या, दोन वेगळे प्रश्न।
एक सत्र सुरू करा, वेळेचे मापन सुरू ठेवा, आणि तुम्हाला महत्त्वाचे असलेले विधान त्याच्या आतून चालवा। सत्र पुन्हा वापरल्यास कनेक्टचा खर्च पहिल्या मापनाबाहेर राहतो।
psql "host=db.internal port=5432 dbname=appdb user=app" \
-c "\timing on" \
-c "select count(*) from orders where created_at > now() - interval '1 day';"संख्येत निकालाचे हस्तांतरण अजूनही आहे, आणि इथे तेच हवे आहे। नवीन कॉल जोडणारी कनेक्ट आणि प्रमाणीकरण देवाणघेवाण आता त्यात नाही।
एक विधान तीन मार्गांवर तुलना करा
तेच विधान Unix सॉकेट, LAN पत्ता आणि VPN होस्ट नावावरून चालवा आणि तीनही तुलना करा। फक्त शेवटचा संथ असेल, तर क्वेरी बदलणारा घटक नाही।
प्रत्येक कॉल प्रथम कनेक्ट होतो आणि मगच विधान मोजतो, त्यामुळे कनेक्टचा खर्च संख्येबाहेर राहतो आणि हस्तांतरण आत राहते। WHERE कलम, ओळींची संख्या आणि क्लायंट मशीन समान ठेवा, अन्यथा तुम्ही मार्ग नव्हे तर कामाचा भार तुलना करत आहात।
psql -h /var/run/postgresql -U app -d appdb -c "\timing on" -c "select count(*) from orders;"
psql -h 10.40.0.12 -U app -d appdb -c "\timing on" -c "select count(*) from orders;"
psql -h db.vpn.internal -U app -d appdb -c "\timing on" -c "select count(*) from orders;"LAN वर फरक सहसा दुर्लक्ष करण्याइतका लहान असतो; VPN वरून अनेकदा नसतो। तीन निकालांची मांडणी केल्यावर कोणत्या प्रतीक्षेवर हल्ला करायचा ते कळते।
संथ स्थानिक सॉकेट म्हणजे सर्व्हरचे काम किंवा नियोजन। संथ LAN निकाल म्हणजे क्वेरी किंवा तिच्याकडून हलणारे प्रमाण। फक्त VPN निकाल संथ असणे म्हणजे मार्गावरील विलंब, MTU किंवा उपलब्ध बँडविड्थ, आणि कोणताही इंडेक्स बदल ते सुधारत नाही।
सर्व्हरचा स्वतःचा अंमलबजावणी वेळ काढा
सर्व्हर किती वेळ खर्च केला हे सांगू शकतो, आणि क्लायंटच्या संख्येसमोर ठेवायची संख्या तीच आहे। ANALYZE सह EXPLAIN विधान चालवतो आणि योजनेच्या आत नियोजन व अंमलबजावणीचा वेळ छापतो, तर BUFFERS कॅशेचे वर्तन जोडतो जे उबदार फेरीचे थंड फेरीशी स्पष्टीकरण अनेकदा देते। लिहायचा इरादा नसल्यास ते लेखन विधानांकडे वळवू नका। फक्त-वाचन प्रतिकृतीवर सुरुवात करण्याची सर्वात सुरक्षित जागा हीच आहे, आणि psql संदर्भ टाइमरची क्लायंट बाजूची व्याप्ती नोंदवतो।
अॅप्लिकेशन आधीच चालवत असलेल्या विधानांसाठी, pg_stat_statements काहीही पुन्हा न चालवता सर्व्हर बाजूची अंमलबजावणी एकत्र करतो। ओळी सामान्यीकृत क्वेरीनुसार असतात, त्यामुळे एक नोंद अनेक कॉल जागा व्यापू शकते।
select calls, round(mean_exec_time::numeric, 2) as mean_ms, rows
from pg_stat_statements
order by mean_exec_time desc
limit 5;स्तंभांची नावे आवृत्तीनुसार बदलतात: PostgreSQL 13 आणि नंतरची mean_exec_time दाखवतात, तर जुन्या आवृत्त्या त्याला mean_time म्हणतात, म्हणून तपासा \d pg_stat_statements ने, जर ती क्वेरी त्रुटी देते। ही मूल्ये नियोजन वगळतात आणि तुमच्या क्लायंटपर्यंतचा प्रवासही वगळतात। हेच वगळणे त्यांना तुलनेसाठी उपयुक्त बनवते।
येणे-जाणे मोजा, फक्त मिलिसेकंद नाही
दोनशे लहान अवलंबून विधानांनी बांधलेला अहवाल मार्ग जोडतो त्या विलंबाला दोनशेने गुणतो। एक दशलक्ष ओळी परत देणारे एक विधान तो विलंब एकदा भरते आणि नंतर बराच वेळ बँडविड्थ भरते। दोन्ही क्लायंट टाइमरमध्ये सारखेच दिसतात, आणि त्यांना विरुद्ध दुरुस्त्या लागतात।
विधानांची संख्या अंदाज न लावता मोजा। एकूण वाचा, अहवाल एकदा चालवा, मग पुन्हा वाचा आणि वजा करा।
select sum(calls) as calls from pg_stat_statements;
-- run the report here
select sum(calls) as calls from pg_stat_statements;डेल्टा मोठा असेल आणि सर्व्हरवर प्रत्येक विधान स्वस्त असेल, तर बॅचिंग ही फळ देणारी दुरुस्ती आहे। अवलंबून क्वेरी एकत्र करा, एक संच-आधारित विधान वापरा, किंवा कर्सरमधून लूप चालवा। परस्परसंवादी psql मध्ये, \set FETCH_COUNT 1000 मोठा निकाल बॅचमध्ये येऊ देतो आणि हस्तांतरण व क्लायंट मेमरीचे वर्तन बदलतो। ते सर्व्हरचे काम कमी करत नाही, त्यामुळे संथ क्वेरी वाचवणार नाही।
टनेलची पुनर्प्रेषणे आणि MTU अडथळे तपासा
जेव्हा लहान विधाने वेगवान असतात आणि मोठे निकाल अर्ध्या वाटेवर थांबतात, तेव्हा क्वेरी सहसा ठीक असते आणि मार्ग नसतो। MTU मूलभूत दुव्यापेक्षा कमी असलेली टनेल, अडवलेल्या ICMP सह, नेमका तोच नमुना तयार करते: पहिले पॅकेट येतात, मोठे गायब होतात, आणि पुन्हा प्रयत्न करेपर्यंत हस्तांतरण लटकते। क्लायंट बाजूचे पुनर्प्रेषण काउंटर ते दाखवतात।
हेतुपुरस्सर संथ हस्तांतरण चालू असताना सॉकेट आणि कर्नेल काउंटर पहा। पुनर्प्रेषणाच्या बेरीज संचयी असतात, म्हणून एक नमुना वाचण्याऐवजी त्या आधी व नंतर नोंदवा।
ss -tin dst 10.40.0.12
netstat -s | grep -iE "retransmit|segments retransmitted"
ping -M do -s 1400 -c 3 10.40.0.12हस्तांतरणादरम्यान वाढणारी पुनर्प्रेषणे, 1400 बाइटवर यशस्वी पण 1472 वर अयशस्वी होणाऱ्या ping सह, डेटाबेस समस्या नव्हे तर MTU समस्या दर्शवतात। टनेल इंटरफेसचे MTU कमी करणे किंवा गेटवेवर MSS दाबणे ही नेहमीची दुरुस्ती आहे, आणि तेच तीन आदेश नंतर त्याची पुष्टी करतात। हस्तांतरण अजूनही संथ असताना पुनर्प्रेषणे सपाट राहिली, तर हानीकडे नव्हे तर टनेलला दिलेल्या बँडविड्थकडे पहा।
छोटा क्रम पुढील संथ अहवाल व्यापतो: एक विधान स्थानिक, LAN वर आणि VPN वरून तुलना करा; EXPLAIN किंवा pg_stat_statements मधून सर्व्हर अंमलबजावणी वाचा; एकदा चालवण्यापूर्वी आणि नंतर कॉल मोजा; आणि मोठा निकाल हलत असताना पुनर्प्रेषणे पहा। प्रत्येक पायरी मार्गाची एक बाजू वगळते। यापैकी कोणीही कोणता घटक पुन्हा सुरू करायचा याचा अंदाज लावायला सांगत नाही।