Jūsu pārskats pabeidzas aptuveni sekundē datubāzes resursdatorā un četrās pa VPN, un skaitlis, ko psql izdrukā, norāda tieši uz datubāzi. Šis skaitlis ir hronometrs klienta pusē, nevis servera mērījums. Tas ietver priekšrakstu ceļā ārā, gaidīšanu uz atbildi un rindas ceļā atpakaļ. Šo trīs atdalīšana ir vienīgais veids, kā uzzināt, kuru pusi regulēt.

Ko psql taimeris patiešām mēra

\timing on iedarbina hronometru tieši pirms klients ieraksta priekšrakstu ligzdā, un aptur to, kad ir nolasīta tā rezultāta pēdējā rinda. Paša servera izpilde atrodas kaut kur šajā logā, un arī katra milisekunde, ko paketes pavada tunelī. Nekas izvadē tās neatdala. EXPLAIN arī izdrukā skaitli, bet to veido serveris, un tas izslēdz klienta gaidīšanu. Divi skaitļi, divi dažādi jautājumi.

Sāciet vienu sesiju, atstājiet laika mērīšanu ieslēgtu un izpildiet priekšrakstu, kas jums svarīgs, no tās iekšienes. Sesijas atkārtota izmantošana savienošanas izmaksas tur ārpus pirmā mērījuma.

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';"

Skaitlis joprojām ietver rezultāta pārsūtīšanu, un tas šeit ir tas, ko vēlaties. Tas vairs neietver savienošanas un autentifikācijas apmaiņu, ko pievienotu jauns izsaukums.

Salīdziniet vienu priekšrakstu trīs ceļos

Izpildiet to pašu priekšrakstu pa Unix ligzdu, pa LAN adresi un pa VPN resursdatora nosaukumu, un salīdziniet trīs. Ja lēns ir tikai pēdējais, vaicājums nav mainīgais.

Katrs izsaukums vispirms savienojas un tikai pēc tam mēra priekšrakstu, tāpēc savienošanas izmaksas paliek ārpus skaitļa, bet pārsūtīšana paliek iekšpusē. Turiet WHERE klauzulu, rindu skaitu un klienta mašīnu identiskus, citādi jūs salīdzināt darba slodzes, nevis ceļus.

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 tīklā atšķirība parasti ir pietiekami maza, lai to ignorētu; pa VPN bieži tā nav. Trīs rezultātu sakārtošana pēc tam pasaka, kuru gaidīšanu uzbrukt.

Lēna vietējā ligzda nozīmē servera darbu vai plānošanu. Lēns LAN rezultāts nozīmē vaicājumu vai tā pārvietoto apjomu. Tikai lēns VPN rezultāts nozīmē aizturi, MTU vai pieejamo joslas platumu ceļā, un nekādas indeksa izmaiņas to neizlabo.

Izvelciet paša servera izpildes laiku

Serveris var ziņot, cik daudz laika tas pavadīja, un tieši šis skaitlis ir jāsalīdzina ar klienta skaitli. EXPLAIN ar ANALYZE izpilda priekšrakstu un izdrukā plānošanas un izpildes laiku plānā, bet BUFFERS pievieno kešatmiņas uzvedību, kas bieži izskaidro siltu gaitu pret aukstu. Nevērsiet to uz rakstīšanas priekšrakstiem, ja neplānojat rakstīt. Tikai lasīšanai paredzētā replikā tā ir drošākā vieta, kur sākt, un psql rokasgrāmata dokumentē taimera apjomu klienta pusē.

Priekšrakstiem, ko lietotne jau izpilda, pg_stat_statements apkopo servera puses izpildi, neko atkārtoti neskrienot. Rindas ir pēc normalizēta vaicājuma, tāpēc viens ieraksts var aptvert vairākas izsaukuma 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;

Kolonnu nosaukumi atšķiras atkarībā no laidiena: PostgreSQL 13 un jaunākas versijas rāda mean_exec_time, bet vecākas versijas to sauc mean_time, tāpēc pārbaudiet ar \d pg_stat_statements, ja šis vaicājums dod kļūdu. Šīs vērtības izslēdz plānošanu un izslēdz ceļu līdz jūsu klientam. Tieši šī izslēgšana padara tās noderīgas salīdzināšanai.

Skaitiet turp-atpakaļ braucienus, ne tikai milisekundes

Pārskats, kas veidots no diviem simtiem mazu atkarīgu priekšrakstu, reizina jebkuru ceļa pievienoto aizturi ar divi simti. Viens priekšraksts, kas atgriež miljonu rindu, samaksā šo aizturi vienreiz un pēc tam ilgi maksā joslas platumu. Abi klienta taimerī izskatās vienādi, un tiem vajadzīgi pretēji labojumi.

Izmēriet priekšrakstu skaitu, nevis to novērtējiet. Nolasiet kopsummu, vienreiz palaidiet pārskatu, pēc tam nolasiet vēlreiz un atņemiet.

select sum(calls) as calls from pg_stat_statements;
-- run the report here
select sum(calls) as calls from pg_stat_statements;

Ja delta ir liela un katrs priekšraksts serverī ir lēts, pakešu apstrāde ir labojums, kas atmaksājas. Apvienojiet atkarīgos vaicājumus, izmantojiet vienu uz kopu balstītu priekšrakstu vai vadiet cilpu no kursora. Interaktīvā psql, \set FETCH_COUNT 1000 liels rezultāts nāk pakešu veidā un maina pārsūtīšanas un klienta atmiņas uzvedību. Tas nesamazina servera darbu, tāpēc neglābs lēnu vaicājumu.

Pārbaudiet tuneli attiecībā uz atkārtotu sūtīšanu un MTU apstāšanos

Kad mazi priekšraksti ir ātri un lieli rezultāti apstājas pusceļā, vaicājums parasti ir kārtībā, bet ceļš nav. Tunelis, kura MTU ir zemāks par pamata saiti, kopā ar bloķētu ICMP rada tieši tādu modeli: pirmās paketes atnāk, lielās pazūd, un pārsūtīšana karājas, līdz tas mēģina vēlreiz. Klienta puses atkārtotas sūtīšanas skaitītāji to parāda.

Vērojiet ligzdu un kodola skaitītājus, kamēr notiek apzināti lēna pārsūtīšana. Atkārtotas sūtīšanas summas ir kumulatīvas, tāpēc pierakstiet tās pirms un pēc, nevis lasiet vienu paraugu.

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

Atkārtotas sūtīšanas, kas aug pārsūtīšanas laikā, kopā ar ping, kas izdodas pie 1400 baitiem, bet neizdodas pie 1472, norāda uz MTU problēmu, nevis datubāzes problēmu. Tunela saskarnes MTU pazemināšana vai MSS saspiešana pie vārtejas ir ierastais labojums, un tie paši trīs komandas to apstiprina pēc tam. Ja atkārtotās sūtīšanas paliek plakanas, kamēr pārsūtīšana joprojām ir lēna, skatieties uz tunelim atļauto joslas platumu, nevis uz zudumiem.

Īsa secība aptver nākamo lēno pārskatu: salīdziniet vienu priekšrakstu lokāli, LAN tīklā un pa VPN; nolasiet servera izpildi no EXPLAIN vai pg_stat_statements; saskaitiet izsaukumus pirms vienas palaišanas un pēc tās; un vērojiet atkārtotas sūtīšanas, kamēr lielais rezultāts kustas. Katrs solis izslēdz vienu ceļa pusi. Nevienam nav jāmin, kuru komponentu restartēt.

Saistītie raksti