Вымярэнне часу psql праз VPN: аддзяленне сеткавага чакання ад працы запыту
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 або даступную прапускную здольнасць на шляху, і ніякія змены індэксаў гэтага не выправяць.
Выцягніце ўласны час выканання сервера
Сервер можа паведаміць, колькі часу ён выдаткаваў, і менавіта гэты лік трэба супастаўляць з лікам кліента. EXPLAIN з ANALYZE выконвае выраз і друкуе час планавання і выканання ўнутры плана, а 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Паўторныя перадачы, якія растуць падчас перадачы, разам з ping, што паспяховы на 1400 байт і няўдалы на 1472, паказваюць на праблему MTU, а не базы даных. Зніжэнне MTU інтэрфейса тунеля або заціск MSS на шлюзе — звычайнае выпраўленне, і тыя ж тры каманды пацвярджаюць яго пасля. Калі паўторныя перадачы застаюцца нязменнымі, пакуль перадача ўсё яшчэ павольная, глядзіце на прапускную здольнасць, дазволеную тунелю, а не на страты.
Кароткая паслядоўнасць пакрывае наступную павольную справаздачу: параўнайце адзін выраз лакальна, у LAN і праз VPN; прачытайце выкананне сервера з EXPLAIN або pg_stat_statements; палічыце выклікі да і пасля аднаго запуску; і назірайце за паўторнымі перадачамі, пакуль рухаецца вялікі вынік. Кожны крок выключае адзін бок шляху. Ні адзін з іх не патрабуе здагадак, які кампанент перазапусціць.