psql laiko matavimas per VPN: tinklo laukimo atskyrimas nuo užklausos darbo
psql praneša vieną praėjusio laiko skaičių kiekvienam teiginiui, todėl lėtas VPN jį išpučia. Atskirkite prisijungimo, vykdymo, perdavimo ir kelionės pirmyn ir atgal laiką, prieš derindami bet kurią pusę.
Jūsų ataskaita baigiama maždaug per sekundę duomenų bazės serveryje ir per keturias per VPN, o skaičius, kurį spausdina psql, rodo tiesiai į duomenų bazę. Tas skaičius yra kliento pusės chronometras, o ne serverio matavimas. Jis apima teiginį kelyje į išorę, laukimą atsakymo ir eilutes kelyje atgal. Atskirti šiuos tris – vienintelis būdas sužinoti, kurią pusę derinti.
Ką psql laikmatis iš tikrųjų matuoja
\timing on paleidžia chronometrą prieš pat klientui įrašant teiginį į lizdą ir sustabdo, kai perskaitoma paskutinė to rezultato eilutė. Paties serverio vykdymas yra kažkur tame lange, taip pat kiekvienas milisekundis, kurį paketai praleidžia tunelyje. Niekas išvestyje jų neatskiria. EXPLAIN taip pat spausdina skaičių, bet jį sukuria serveris, ir jis neapima kliento laukimo. Du skaičiai, du skirtingi klausimai.
Pradėkite vieną sesiją, palikite laiko matavimą įjungtą ir vykdykite teiginį, kuris jums svarbus, iš jos vidaus. Sesijos pakartotinis naudojimas prisijungimo kaštą palieka už pirmojo matavimo ribų.
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';"Skaičius vis dar apima rezultato perdavimą, o čia būtent to ir norite. Jis nebeapima prisijungimo ir autentifikavimo mainų, kuriuos pridėtų naujas iškvietimas.
Palyginkite vieną teiginį trimis keliais
Vykdykite tą patį teiginį per Unix lizdą, per LAN adresą ir per VPN serverio vardą, ir palyginkite tris. Jei lėtas tik paskutinis, užklausa nėra kintamasis.
Kiekvienas iškvietimas pirmiausia prisijungia ir tik tada matuoja teiginį, todėl prisijungimo kaštai lieka už skaičiaus, o perdavimas lieka viduje. Laikykite WHERE sąlygą, eilučių skaičių ir kliento mašiną identiškus, kitaip lyginate darbo krūvius, o ne kelius.
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 tinkle skirtumas paprastai būna pakankamai mažas, kad jį ignoruotumėte; per VPN dažnai ne. Trijų rezultatų surikiavimas tada pasako, kurį laukimą pulti.
Lėtas vietinis lizdas reiškia serverio darbą arba planavimą. Lėtas LAN rezultatas reiškia užklausą arba jos perkeliamą apimtį. Tik lėtas VPN rezultatas reiškia delsą, MTU arba laisvą pralaidumą kelyje, ir jokie indeksų pakeitimai to neištaiso.
Ištraukite paties serverio vykdymo laiką
Serveris gali pranešti, kiek laiko praleido, ir būtent šį skaičių reikia lyginti su kliento. EXPLAIN su ANALYZE įvykdo teiginį ir plane atspausdina planavimo bei vykdymo laiką, o BUFFERS prideda podėlio elgseną, kuri dažnai paaiškina šiltą eigą prieš šaltą. Nenukreipkite jo į rašymo teiginius, jei neketinate rašyti. Tik skaitymui skirtoje replikoje tai saugiausia vieta pradėti, ir psql žinynas dokumentuoja laikmačio apimtį kliento pusėje.
Teiginiams, kuriuos programa jau vykdo, pg_stat_statements sukaupia serverio pusės vykdymą nieko nekartodamas. Eilutės pateikiamos pagal normalizuotą užklausą, todėl vienas įrašas gali apimti kelias iškvietimo vietas.
select calls, round(mean_exec_time::numeric, 2) as mean_ms, rows
from pg_stat_statements
order by mean_exec_time desc
limit 5;Stulpelių pavadinimai skiriasi pagal leidimą: PostgreSQL 13 ir naujesnės versijos rodo mean_exec_time, o senesnės versijos jį vadina mean_time, todėl patikrinkite su \d pg_stat_statements, jei ši užklausa grąžina klaidą. Šios reikšmės neapima planavimo ir neapima kelionės iki jūsų kliento. Būtent šis neįtraukimas daro jas naudingas palyginimui.
Skaičiuokite keliones pirmyn ir atgal, ne tik milisekundes
Ataskaita, sudaryta iš dviejų šimtų mažų priklausomų teiginių, padaugina bet kokią kelio pridedamą delsą iš dviejų šimtų. Vienas teiginys, grąžinantis milijoną eilučių, sumoka tą delsą vieną kartą ir po to ilgai moka pralaidumą. Abu kliento laikmatyje atrodo vienodai, ir jiems reikia priešingų pataisų.
Išmatuokite teiginių skaičių, o ne jį vertinkite. Perskaitykite sumą, vieną kartą paleiskite ataskaitą, tada perskaitykite vėl ir atimkite.
select sum(calls) as calls from pg_stat_statements;
-- run the report here
select sum(calls) as calls from pg_stat_statements;Jei delta didelė ir kiekvienas teiginys serveryje pigus, paketinis vykdymas yra pataisa, kuri atsiperka. Sujunkite priklausomas užklausas, naudokite vieną rinkiniu pagrįstą teiginį arba valdykite ciklą iš žymeklio. Interaktyviame psql, \set FETCH_COUNT 1000 didelis rezultatas ateina paketais ir pakinta perdavimo bei kliento atminties elgsena. Tai nesumažina serverio darbo, todėl neišgelbės lėtos užklausos.
Patikrinkite tunelį dėl pakartotinio siuntimo ir MTU sustojimų
Kai maži teiginiai greiti, o dideli rezultatai sustoja pusiaukelėje, užklausa paprastai tvarkinga, o kelias ne. Tunelis, kurio MTU mažesnis už pagrindinę jungtį, kartu su užblokuotu ICMP, sukuria būtent tokį modelį: pirmieji paketai ateina, didieji dingsta, ir perdavimas kabo, kol jis vėl bando. Kliento pusės pakartotinio siuntimo skaitikliai tai rodo.
Stebėkite lizdą ir branduolio skaitiklius, kol vyksta sąmoningai lėtas perdavimas. Pakartotinio siuntimo sumos yra kaupiamosios, todėl užsirašykite jas prieš ir po, o ne skaitykite vieną pavyzdį.
ss -tin dst 10.40.0.12
netstat -s | grep -iE "retransmit|segments retransmitted"
ping -M do -s 1400 -c 3 10.40.0.12Pakartotiniai siuntimai, augantys perdavimo metu, kartu su ping, kuris pavyksta ties 1400 baitų, bet nepavyksta ties 1472, rodo MTU problemą, o ne duomenų bazės problemą. Tunelio sąsajos MTU sumažinimas arba MSS suspaudimas ties tinklų sietuvu yra įprasta pataisa, ir tie patys trys įsakymai tai patvirtina vėliau. Jei pakartotiniai siuntimai išlieka plokšti, kol perdavimas vis dar lėtas, žiūrėkite į tuneliui leidžiamą pralaidumą, o ne į nuostolius.
Trumpa seka apima kitą lėtą ataskaitą: palyginkite vieną teiginį vietoje, LAN tinkle ir per VPN; perskaitykite serverio vykdymą iš EXPLAIN arba pg_stat_statements; suskaičiuokite iškvietimus prieš vieną paleidimą ir po jo; ir stebėkite pakartotinius siuntimus, kol didelis rezultatas juda. Kiekvienas žingsnis atmeta vieną kelio pusę. Nė vienam nereikia spėlioti, kurį komponentą paleisti iš naujo.