Ano ang tahimik tungkol sa EXPLAIN at kung paano ito maituturing

Ang klasikong tanong na dinadala ng isang developer sa kanyang DBA o isang may-ari ng negosyo sa isang consultant ng PostgreSQL ay halos palaging pareho ang tunog: "Bakit napakatagal bago makumpleto ang mga kahilingan sa database?"

Tradisyonal na hanay ng mga dahilan:

  • hindi mahusay na algorithm
    kapag nagpasya kang SUMALI sa ilang CTE sa loob ng ilang sampu-sampung libong talaan
  • hindi nauugnay na istatistika
    kung ang aktwal na distribusyon ng data sa talahanayan ay ibang-iba na sa nakolekta ng ANALYZE noong nakaraang panahon
  • "plug" sa mga mapagkukunan
    at wala nang sapat na dedikadong computing power ng CPU, ang mga gigabytes ng memorya ay patuloy na ipinobomba, o ang disk ay hindi makakasabay sa lahat ng "gusto" ng database
  • hinaharang mula sa mga prosesong nakikipagkumpitensya

At kung ang mga pagharang ay medyo mahirap hulihin at pag-aralan, kung gayon para sa lahat ng iba pang kailangan namin plano ng pagtatanong, na maaaring makuha gamit ang Ipaliwanag ang operator (Mas mainam, siyempre, na agad na IPALIWANAG (ANALYZE, BUFFERS) ...) o auto_explain module.

Ngunit, tulad ng nakasaad sa parehong dokumentasyon,

"Ang pag-unawa sa isang plano ay isang sining, at upang makabisado ito ay nangangailangan ng isang tiyak na dami ng karanasan..."

Ngunit magagawa mo nang wala ito kung gagamitin mo ang tamang tool!

Ano ang karaniwang hitsura ng isang query plan? Isang bagay na tulad nito:

Index Scan using pg_class_relname_nsp_index on pg_class (actual time=0.049..0.050 rows=1 loops=1)
  Index Cond: (relname = $1)
  Filter: (oid = $0)
  Buffers: shared hit=4
  InitPlan 1 (returns $0,$1)
    ->  Limit (actual time=0.019..0.020 rows=1 loops=1)
          Buffers: shared hit=1
          ->  Seq Scan on pg_class pg_class_1 (actual time=0.015..0.015 rows=1 loops=1)
                Filter: (relkind = 'r'::"char")
                Rows Removed by Filter: 5
                Buffers: shared hit=1

o ganito:

"Append  (cost=868.60..878.95 rows=2 width=233) (actual time=0.024..0.144 rows=2 loops=1)"
"  Buffers: shared hit=3"
"  CTE cl"
"    ->  Seq Scan on pg_class  (cost=0.00..868.60 rows=9972 width=537) (actual time=0.016..0.042 rows=101 loops=1)"
"          Buffers: shared hit=3"
"  ->  Limit  (cost=0.00..0.10 rows=1 width=233) (actual time=0.023..0.024 rows=1 loops=1)"
"        Buffers: shared hit=1"
"        ->  CTE Scan on cl  (cost=0.00..997.20 rows=9972 width=233) (actual time=0.021..0.021 rows=1 loops=1)"
"              Buffers: shared hit=1"
"  ->  Limit  (cost=10.00..10.10 rows=1 width=233) (actual time=0.117..0.118 rows=1 loops=1)"
"        Buffers: shared hit=2"
"        ->  CTE Scan on cl cl_1  (cost=0.00..997.20 rows=9972 width=233) (actual time=0.001..0.104 rows=101 loops=1)"
"              Buffers: shared hit=2"
"Planning Time: 0.634 ms"
"Execution Time: 0.248 ms"

Ngunit ang pagbabasa ng plano sa teksto "mula sa sheet" ay napakahirap at hindi malinaw:

  • ay ipinapakita sa node kabuuan ng mga mapagkukunan ng subtree
    iyon ay, upang maunawaan kung gaano karaming oras ang kinuha upang maisagawa ang isang partikular na node, o kung gaano eksakto ang pagbabasa na ito mula sa talahanayan ay nagdala ng data mula sa disk, kailangan mong ibawas ang isa mula sa isa pa.
  • kailangan ng oras ng node multiply sa pamamagitan ng mga loop
    oo, ang pagbabawas ay hindi ang pinaka kumplikadong operasyon na kailangang gawin "sa ulo" - pagkatapos ng lahat, ang oras ng pagpapatupad ay ipinahiwatig bilang average para sa isang pagpapatupad ng isang node, at maaaring magkaroon ng daan-daang mga ito
  • mabuti, at ang lahat ng ito nang magkakasama ay pumipigil sa amin na sagutin ang pangunahing tanong - kaya sino "ang pinakamahina na link"?

Nang sinubukan naming ipaliwanag ang lahat ng ito sa ilang daang aming mga developer, napagtanto namin na mula sa labas ay ganito ang hitsura nito:

Ano ang tahimik tungkol sa EXPLAIN at kung paano ito maituturing

At ibig sabihin, kailangan natin...

Kasangkapan

Sa loob nito sinubukan naming kolektahin ang lahat ng mga pangunahing mekanika na makakatulong sa pag-unawa sa "sino ang dapat sisihin at kung ano ang gagawin" ayon sa plano at kahilingan. Well, at ibahagi ang bahagi ng iyong karanasan sa komunidad.
Kilalanin at gamitin - explain.tensor.ru

Visibility ng mga plano

Madali bang intindihin ang plano kapag ganito ang hitsura?

Seq Scan on pg_class (actual time=0.009..1.304 rows=6609 loops=1)
  Buffers: shared hit=263
Planning Time: 0.108 ms
Execution Time: 1.800 ms

Hindi talaga.

Ngunit tulad nito, sa pinaikling anyokapag ang mga pangunahing tagapagpahiwatig ay pinaghiwalay, ito ay mas malinaw:

Ano ang tahimik tungkol sa EXPLAIN at kung paano ito maituturing

Ngunit kung ang plano ay mas kumplikado, siya ay darating upang iligtas pamamahagi ng oras ng piechart sa pamamagitan ng mga node:

Ano ang tahimik tungkol sa EXPLAIN at kung paano ito maituturing

Buweno, para sa pinakamahirap na mga pagpipilian ay nagmamadali siyang tumulong tsart ng pag-unlad:

Ano ang tahimik tungkol sa EXPLAIN at kung paano ito maituturing

Halimbawa, may mga hindi mahalaga na sitwasyon kapag ang isang plano ay maaaring magkaroon ng higit sa isang aktwal na ugat:

Ano ang tahimik tungkol sa EXPLAIN at kung paano ito maituturingAno ang tahimik tungkol sa EXPLAIN at kung paano ito maituturing

Mga pahiwatig sa istruktura

Buweno, kung ang buong istraktura ng plano at ang mga masakit na lugar nito ay inilatag at nakikita na, bakit hindi i-highlight ang mga ito sa developer at ipaliwanag ang mga ito sa "wika ng Ruso"?

Ano ang tahimik tungkol sa EXPLAIN at kung paano ito maituturingNakakolekta na kami ng ilang dosenang mga template ng rekomendasyon.

Line-by-line na query profiler

Ngayon, kung ipapatong mo ang orihinal na query sa nasuri na plano, makikita mo kung gaano katagal ang ginugol sa bawat indibidwal na pahayag - tulad nito:

Ano ang tahimik tungkol sa EXPLAIN at kung paano ito maituturing

...o kahit ganito:

Ano ang tahimik tungkol sa EXPLAIN at kung paano ito maituturing

Pagpapalit ng mga parameter sa isang kahilingan

Kung "naka-attach" ka hindi lamang ng isang kahilingan sa plano, kundi pati na rin ang mga parameter nito mula sa DETAIL na linya ng log, maaari mo itong kopyahin sa isa sa mga opsyon:

  • na may pagpapalit ng halaga sa kahilingan
    para sa direktang pagpapatupad sa iyong base at karagdagang pag-profile

    SELECT 'const', 'param'::text;
  • na may pagpapalit ng halaga sa pamamagitan ng PREPARE/EXECUTE
    upang tularan ang gawain ng scheduler, kapag ang parametric na bahagi ay maaaring balewalain - halimbawa, kapag nagtatrabaho sa mga partitioned table

    DEALLOCATE ALL;
    PREPARE q(text) AS SELECT 'const', $1::text;
    EXECUTE q('param'::text);
    

Archive ng mga plano

I-paste, pag-aralan, ibahagi sa mga kasamahan! Ang mga plano ay mananatiling naka-archive at maaari kang bumalik sa kanila sa ibang pagkakataon: explain.tensor.ru/archive

Ngunit kung ayaw mong makita ng iba ang iyong plano, huwag kalimutang lagyan ng tsek ang kahon na "huwag i-publish sa archive".

Sa mga susunod na artikulo ay pag-uusapan ko ang tungkol sa mga kahirapan at desisyon na lalabas kapag nagsusuri ng isang plano.

Pinagmulan: www.habr.com

Magdagdag ng komento