PostgreSQL Query Profiler: kumaha cocog rencana sareng pamundut

Loba anu geus ngagunakeun explain.tensor.ru - jasa visualisasi rencana PostgreSQL urang bisa jadi teu sadar salah sahiji adidaya na - ngarobah sapotong hard-to-baca log server ...

PostgreSQL Query Profiler: kumaha cocog rencana sareng pamundut
... kana pamundut anu dirarancang saé kalayan petunjuk kontekstual pikeun titik rencana anu saluyu:

PostgreSQL Query Profiler: kumaha cocog rencana sareng pamundut
Dina transkrip ieu bagian kadua na laporan di PGConf.Russia 2020 Kuring gé ngabejaan Anjeun kumaha urang junun ngalakukeun ieu.

С транскриптом первой части, посвященной типовым проблемам производительности запросов и их решениям, можно ознакомиться в статье "Resep pikeun queries SQL gering".



Mimiti, hayu urang ngamimitian ngawarnaan - sareng urang moal deui ngawarnaan rencanana, kami parantos ngawarnaan, kami parantos ngagaduhan anu saé sareng kaharti, tapi pamenta.

Éta sigana urang yén kalayan "lambar" anu teu diformat sapertos pamundut anu ditarik tina log katingalina awon pisan sahingga henteu pikaresepeun.
PostgreSQL Query Profiler: kumaha cocog rencana sareng pamundut

Utamana lamun pamekar "lem" awak pamundut dina kode (ieu, tangtosna, hiji antipattern, tapi kajadian) dina hiji garis. pikareueuseun!

Hayu urang ngagambar ieu kumaha bae leuwih beautifully.
PostgreSQL Query Profiler: kumaha cocog rencana sareng pamundut

Sareng upami urang tiasa ngagambar ieu sacara saé, nyaéta, ngabongkar sareng ngahijikeun deui awak pamundut, maka urang teras tiasa "ngagantelkeun" petunjuk ka unggal obyék pamundut ieu - naon anu kajantenan dina titik anu saluyu dina rencana.

Tangkal sintaksis pamundut

Jang ngalampahkeun ieu, pamundut kudu parsed munggaran.
PostgreSQL Query Profiler: kumaha cocog rencana sareng pamundut

Kusabab urang boga inti sistem dijalankeun dina NodeJS, lajeng urang dijieun modul pikeun eta, Anjeun tiasa manggihan eta dina GitHub. Kanyataanna, ieu diperpanjang "bindings" kana internal tina parser PostgreSQL sorangan. Hartina, grammar ngan saukur binér disusun sareng beungkeutan dilakukeun tina NodeJS. Kami nyandak modul jalma sanés salaku dasar - teu aya rusiah anu ageung di dieu.

Urang eupan awak pamundut salaku input pikeun fungsi urang - dina kaluaran kami meunang tangkal sintaksis parsed dina bentuk hiji objek JSON.
PostgreSQL Query Profiler: kumaha cocog rencana sareng pamundut

Ayeuna urang bisa ngajalankeun ngaliwatan tangkal ieu dina arah nu lalawanan jeung ngumpul pamundut jeung indents, ngawarnaan, jeung pormat nu urang hayang. Henteu, ieu henteu tiasa disaluyukeun, tapi sigana urang yén ieu bakal pikaresepeun.
PostgreSQL Query Profiler: kumaha cocog rencana sareng pamundut

Mapping query jeung rencana titik

Ayeuna hayu urang tingali kumaha urang tiasa ngagabungkeun rencana anu urang analisa dina léngkah munggaran sareng pamundut anu dianalisis dina kadua.

Hayu urang nyandak conto saderhana - urang gaduh pamundut anu ngahasilkeun CTE sareng maca dua kali. Anjeunna ngahasilkeun rencana sapertos kitu.
PostgreSQL Query Profiler: kumaha cocog rencana sareng pamundut

CTE

Upami ditingali sacara saksama, dugi ka vérsi 12 (atanapi mimitian ku kecap konci MATERIALIZED) formasi CTE mangrupa panghalang mutlak pikeun Nu Ngarencana.
PostgreSQL Query Profiler: kumaha cocog rencana sareng pamundut

Ieu ngandung harti yén lamun urang ningali generasi CTE wae dina pamundut jeung titik hiji tempat di rencana CTE, mangka titik ieu pasti "tarung" saling, urang bisa langsung ngagabungkeun aranjeunna.

Masalah sareng tanda bintang: CTEs bisa nested.
PostgreSQL Query Profiler: kumaha cocog rencana sareng pamundut
Aya pisan kirang nested, komo nu ngaranna sarua. Contona, anjeun tiasa di jero CTE A nyieun CTE X, sareng dina tingkat anu sami di jero CTE B ngalakukeun deui CTE X:

WITH A AS (
  WITH X AS (...)
  SELECT ...
)
, B AS (
  WITH X AS (...)
  SELECT ...
)
...

При сопоставлении вы должны это понимать. Понимать это «глазами» — даже видя план, даже видя тело запроса — очень тяжело. Если у вас генерация CTE сложная, вложенная, запросы большие — тогда и вовсе неосознаваемо.

ngahijikeun

Upami urang gaduh kecap konci dina pamundut UNION [ALL] (operator of gabung dua sampel), lajeng dina rencana eta pakait boh titik a Append, atawa sababaraha Recursive Union.
PostgreSQL Query Profiler: kumaha cocog rencana sareng pamundut

Anu "di luhur" di luhur UNION - ieu teh turunan mimiti titik urang, nu "handap" - kadua. Lamun ngaliwatan UNION urang gaduh sababaraha blok "glued" sakaligus, lajeng Append-masih aya ngan hiji titik, tapi moal boga dua, tapi loba barudak - dina urutan maranéhna balik, masing-masing:

  (...) -- #1
UNION ALL
  (...) -- #2
UNION ALL
  (...) -- #3

Append
  -> ... #1
  -> ... #2
  -> ... #3

Masalah sareng tanda bintang: jero generasi sampling rekursif (WITH RECURSIVE) ogé bisa leuwih ti hiji UNION. Tapi ngan blok anu terakhir saatos anu terakhir sok rekursif UNION. Sagalana di luhur hiji, tapi béda UNION:

WITH RECURSIVE T AS(
  (...) -- #1
UNION ALL
  (...) -- #2, тут кончается генерация стартового состояния рекурсии
UNION ALL
  (...) -- #3, только этот блок рекурсивный и может содержать обращение к T
)
...

Anjeun ogé kedah tiasa "nempelkeun" conto sapertos kitu. Dina conto ieu urang tingali éta UNION-aya 3 bagéan dina pamundut urang. Sasuai, hiji UNION соответствует Append-node, sareng anu sanés- Recursive Union.
PostgreSQL Query Profiler: kumaha cocog rencana sareng pamundut

Data baca-tulis

Sagalana geus diteundeun kaluar, ayeuna urang terang nu sapotong pamundut pakait jeung nu sapotong rencana. Sareng dina potongan-potongan ieu urang tiasa kalayan gampang sareng alami mendakan barang-barang anu "bisa dibaca".

С точки зрения запроса мы не знаем — таблица это или CTE, но обозначаются они одинаковым узлом RangeVar. Sareng tina segi "kabaca", ieu ogé mangrupikeun set titik anu cukup terbatas:

  • Seq Scan on [tbl]
  • Bitmap Heap Scan on [tbl]
  • Index [Only] Scan [Backward] using [idx] on [tbl]
  • CTE Scan on [cte]
  • Insert/Update/Delete on [tbl]

Urang terang struktur rencana sareng pamundut, urang terang korespondensi blok, urang terang nami objék - urang ngabandingkeun hiji-ka-hiji.
PostgreSQL Query Profiler: kumaha cocog rencana sareng pamundut

Deui tugas "kalayan tanda bintang". Kami nyandak pamundut, laksanakeun, kami henteu ngagaduhan alias - kami ngan ukur maca dua kali tina CTE anu sami.
PostgreSQL Query Profiler: kumaha cocog rencana sareng pamundut

Urang nempo rencana - naon masalahna? Naha urang boga alias? Kami henteu mesen. Dimana anjeunna kéngingkeun "nomer nomer" sapertos kitu?

PostgreSQL nambihanana sorangan. Anjeun ngan kedah ngartos éta именно такой алиас keur urang, keur kaperluan ngabandingkeun jeung rencana, teu make akal pikiran, ngan ditambahkeun dieu. Hayu urang teu merhatikeun anjeunna.

kadua tugas "kalayan tanda bintang": lamun urang maca tina tabel partitioned, mangka urang bakal meunang titik Append atawa Merge Append, nu bakal diwangun ku angka nu gede ngarupakeun "barudak", sarta masing-masing bakal kumaha bae Scan'om tina tabel bagian: Seq Scan, Bitmap Heap Scan atawa Index Scan. Tapi, dina sagala hal, "barudak" ieu moal janten patarosan anu rumit - ieu kumaha titik-titik ieu tiasa dibédakeun tina Append dina UNION.
PostgreSQL Query Profiler: kumaha cocog rencana sareng pamundut

Kami ogé ngartos knots sapertos kitu, kumpulkeun "dina hiji tumpukan" sareng ucapkeun: "sadayana anu anjeun baca tina megatable aya di dieu sareng ka handap tangkal".

"Basajan" data narima titik

PostgreSQL Query Profiler: kumaha cocog rencana sareng pamundut

Values Scan pakait dina rencana VALUES dina pamundut.

Result nyaéta pamundut tanpa FROM nurun tina SELECT 1. Atawa mun anjeun boga éksprési ngahaja palsu di WHERE-block (lajeng atribut mucunghul One-Time Filter):

EXPLAIN ANALYZE
SELECT * FROM pg_class WHERE FALSE; -- или 0 = 1

Result  (cost=0.00..0.00 rows=0 width=230) (actual time=0.000..0.000 rows=0 loops=1)
  One-Time Filter: false

Function Scan "peta" ka SRFs tina nami nu sami.

Tapi kalayan queries nested sagalana leuwih pajeulit - hanjakalna, maranéhna teu salawasna robah jadi InitPlan/SubPlan. Kadang-kadang maranehna ngahurungkeun kana ... Join atawa ... Anti Join, utamana mun anjeun nulis hal kawas WHERE NOT EXISTS .... Sareng di dieu henteu salawasna mungkin pikeun ngagabungkeun aranjeunna - dina téks rencana henteu aya operator anu pakait sareng titik rencana.

Deui tugas "kalayan tanda bintang": sababaraha VALUES dina pamundut. Dina hal ieu sareng dina rencana anjeun bakal nampi sababaraha titik Values Scan.
PostgreSQL Query Profiler: kumaha cocog rencana sareng pamundut

Sufiks "Numbered" bakal ngabantosan ngabédakeunana - aranjeunna ditambihan persis dina urutan anu saluyu. VALUES-blok sapanjang pamundut ti luhur ka handap.

Ngolah data

Sigana mah sagalana dina pamundut urang geus diurutkeun kaluar - kabeh nu ditinggalkeun téh Limit.
PostgreSQL Query Profiler: kumaha cocog rencana sareng pamundut

Tapi di dieu sagalana basajan - titik kayaning Limit, Sort, Aggregate, WindowAgg, Unique "peta" hiji-ka-hiji ka operator saluyu dina pamundut nu, lamun aranjeunna aya. Henteu aya "béntang" atanapi kasusah di dieu.
PostgreSQL Query Profiler: kumaha cocog rencana sareng pamundut

gabung

Kasusah timbul nalika urang hoyong ngahiji JOIN antara sorangan. Ieu teu salawasna mungkin, tapi mungkin.
PostgreSQL Query Profiler: kumaha cocog rencana sareng pamundut

Tina sudut pandang parser pamundut, urang gaduh node JoinExpr, nu boga anak persis dua - kénca jeung katuhu. Ieu, sasuai, nyaeta naon "di luhur" JOIN anjeun sarta naon ditulis "handap" eta dina pamundut teh.

Sareng tina sudut pandang rencana, ieu mangrupikeun dua turunan sababaraha * Loop/* Join- node. Nested Loop, Hash Anti Join,... - siga kitu.

Hayu urang nganggo logika saderhana: upami urang gaduh tabel A sareng B anu "ngagabung" masing-masing dina rencana, maka dina pamundut aranjeunna tiasa ditempatkeun boh. A-JOIN-Batawa B-JOIN-A. Hayu urang coba pikeun ngagabungkeun cara ieu, hayu urang coba pikeun ngagabungkeun sabalikna, jeung saterusna nepi ka béak pasangan saperti.

Возьмем наше синтаксическое дерево, возьмем наш план, посмотрим на них… непохоже!
PostgreSQL Query Profiler: kumaha cocog rencana sareng pamundut

Hayu urang ngagambar deui dina bentuk grafik - oh, éta sigana sapertos kitu!
PostgreSQL Query Profiler: kumaha cocog rencana sareng pamundut

Catet yén urang gaduh titik anu sakaligus ngagaduhan murangkalih B sareng C - urang henteu paduli dina urutan naon. Hayu urang ngagabungkeun aranjeunna sarta balikkeun gambar tina titik.
PostgreSQL Query Profiler: kumaha cocog rencana sareng pamundut

Hayu urang tingali deui. Ayeuna urang gaduh titik sareng barudak A sareng pasangan (B + C) - cocog sareng aranjeunna ogé.
PostgreSQL Query Profiler: kumaha cocog rencana sareng pamundut

Hebat! Tétéla urang duaan ieu JOIN ti pamundut jeung titik rencana anu hasil digabungkeun.

Alas, masalah ieu teu salawasna direngsekeun.
PostgreSQL Query Profiler: kumaha cocog rencana sareng pamundut

Contona, upami dina pamundut A JOIN B JOIN C, Sarta dina rencana, mimiti sagala, "luar" titik A jeung C disambungkeun. Tapi euweuh operator misalna dina pamundut, urang nganggur nyorot, nanaon ngagantelkeun hint ka. Éta sami sareng "koma" nalika anjeun nyerat A, B.

Tapi, dina kalolobaan kasus, ampir sadaya titik tiasa "dibeungkeut" sareng anjeun tiasa nampi profil sapertos kitu di kénca dina waktosna - sacara harfiah, sapertos dina Google Chrome nalika anjeun nganalisis kode JavaScript. Anjeun tiasa ningali sabaraha lila unggal baris jeung unggal pernyataan nyandak "ngaéksekusi".
PostgreSQL Query Profiler: kumaha cocog rencana sareng pamundut

Sarta sangkan eta leuwih merenah pikeun anjeun ngagunakeun sakabéh ieu, kami geus dijieun gudang arsip, dimana anjeun tiasa nyimpen sarta engké manggihan rencana anjeun babarengan jeung requests pakait atawa babagi tumbu ka batur.

Upami anjeun ngan ukur kedah nyangking pamundut anu teu tiasa dibaca kana bentuk anu nyukupan, paké "normalizer" urang.

PostgreSQL Query Profiler: kumaha cocog rencana sareng pamundut

sumber: www.habr.com

Tambahkeun komentar