О чему ЕКСПЛАИН ћути и како га натерати да проговори

Класично питање које програмер поставља свом ДБА-у или власник предузећа доноси ПостгреСКЛ консултанту скоро увек звучи исто: „Зашто је потребно толико времена да се доврше захтеви у бази података?“

Традиционални скуп разлога:

  • неефикасан алгоритам
    када одлучите да СЕ ПРИДРУЖИТЕ неколико ЦТЕ-ова на неколико десетина хиљада записа
  • небитне статистике
    ако је стварна дистрибуција података у табели већ веома различита од оне коју је АНАЛИЗА прикупила прошли пут
  • „прикључити” ресурсе
    и више нема довољно наменске рачунарске снаге ЦПУ-а, гигабајти меморије се стално пумпају или диск не може да прати све „жеље“ базе података
  • блокирање од конкурентских процеса

А ако је блокаде прилично тешко ухватити и анализирати, онда за све остало што нам је потребно план упита, који се може добити помоћу ЕКСПЛАИН оператор (Боље је, наравно, одмах ОБЈАСНИТИ (АНАЛИЗА, БАФЕРИ) ...) или модул ауто_екплаин.

Али, како се наводи у истој документацији,

„Разумевање плана је уметност, а да би се њиме савладало потребно је одређено искуство...“

Али можете и без тога ако користите прави алат!

Како обично изгледа план упита? Нешто налик томе:

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

или овако:

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

Али читање плана у тексту „са листа“ је веома тешко и нејасно:

  • се приказује у чвору збир по ресурсима подстабла
    то јест, да бисте разумели колико је времена било потребно да се изврши одређени чвор, или колико је тачно ово читање из табеле донело податке са диска, морате некако да одузмете једно од другог
  • потребно је време чвора помножити петљама
    да, одузимање није најкомплекснија операција коју треба урадити "у глави" - на крају крајева, време извршења је назначено као просек за једно извршење чвора, а може их бити на стотине
  • па, а све ово заједно нас спречава да одговоримо на главно питање – па ко "најслабија карика"?

Када смо покушали да објаснимо све ово неколико стотина наших програмера, схватили смо да то споља изгледа отприлике овако:

О чему ЕКСПЛАИН ћути и како га натерати да проговори

А то значи да нам треба...

Алат

У њему смо покушали да прикупимо све кључне механике који помажу да се разуме „ко је крив и шта да се ради“ према плану и захтеву. Па, и поделите део свог искуства са заједницом.
Упознајте и користите - објасни.тенсор.ру

Видљивост планова

Да ли је лако разумети план када изгледа овако?

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

Не баш.

али овако, у скраћеном обликукада су кључни индикатори раздвојени, много је јасније:

О чему ЕКСПЛАИН ћути и како га натерати да проговори

Али ако је план компликованији, он ће прискочити у помоћ пиецхарт временска дистрибуција по чворовима:

О чему ЕКСПЛАИН ћути и како га натерати да проговори

Па, за најтеже опције жури да помогне графикон напретка:

О чему ЕКСПЛАИН ћути и како га натерати да проговори

На пример, постоје прилично нетривијалне ситуације када план може имати више од једног стварног корена:

О чему ЕКСПЛАИН ћути и како га натерати да проговориО чему ЕКСПЛАИН ћути и како га натерати да проговори

Структурни трагови

Па, ако су цела структура плана и његове болне тачке већ постављене и видљиве, зашто их не истакнути програмеру и објаснити их на „руском језику“?

О чему ЕКСПЛАИН ћути и како га натерати да проговориВећ смо прикупили неколико десетина таквих шаблона препорука.

Профилер упита ред по ред

Сада, ако ставите оригинални упит на анализирани план, можете видети колико је времена потрошено на сваки појединачни исказ - отприлике овако:

О чему ЕКСПЛАИН ћути и како га натерати да проговори

...или чак овако:

О чему ЕКСПЛАИН ћути и како га натерати да проговори

Замена параметара у захтев

Ако сте плану „приложили“ не само захтев, већ и његове параметре из ДЕТАИЛ линије дневника, можете га додатно копирати у једној од опција:

  • са заменом вредности у упиту
    за директно извођење на вашој бази и даље профилисање

    SELECT 'const', 'param'::text;
  • са заменом вредности преко ПРЕПАРЕ/ЕКСЕЦУТЕ
    да емулира рад планера, када се параметарски део може занемарити - на пример, када се ради на партиционисаним табелама

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

Архива планова

Налепите, анализирајте, поделите са колегама! Планови ће остати архивирани и касније им се можете вратити: објасни.тенсор.ру/арцхиве

Али ако не желите да други виде ваш план, не заборавите да означите поље „не објављуј у архиви“.

У наредним чланцима ћу говорити о потешкоћама и одлукама које се јављају приликом анализе плана.

Извор: ввв.хабр.цом

Додај коментар