તમારો રિપોર્ટ ડેટાબેઝ હોસ્ટ પર લગભગ એક સેકન્ડમાં અને 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 માંથી સર્વર એક્ઝિક્યુશન વાંચો; એક ચાલ પહેલાં અને પછી કૉલ ગણો; અને મોટું પરિણામ ખસે ત્યારે ફરી-પ્રેષણ પર નજર રાખો. દરેક પગલું માર્ગની એક બાજુ બાદ કરે છે. એમાંથી કોઈ પણ કયો ઘટક ફરી શરૂ કરવો તે અનુમાન કરવાનું કહેતું નથી.

સંબંધિત લેખો