Әзірлеуші өзінің DBA немесе бизнес иесі PostgreSQL кеңесшісіне беретін классикалық сұрақ әрқашан бірдей естіледі: «Сұраныстардың дерекқорда аяқталуы неге ұзаққа созылады?»
Дәстүрлі себептер жиынтығы:
- тиімсіз алгоритм
бірнеше ондаған мың жазбалардан астам бірнеше CTE-ге ҚОСЫЛУ туралы шешім қабылдағанда - маңызды емес статистика
егер кестедегі деректердің нақты таралуы ANALYZE соңғы рет жинағанынан мүлдем басқаша болса - ресурстарға «қосу».
және бұдан былай орталық процессордың арнайы есептеу қуаты жеткіліксіз, гигабайт жады үнемі айдалады немесе диск дерекқордың барлық «қалауларына» төтеп бере алмайды. - бұғаттау бәсекелес процестерден
Ал егер бұғаттауларды ұстап алу және талдау өте қиын болса, қалғандарының бәрі үшін бізге қажет сұрау жоспарыпайдалану арқылы алуға болады
Бірақ сол құжаттамада айтылғандай,
«Жоспарды түсіну - өнер, ал оны меңгеру үшін белгілі бір тәжірибе қажет...»
Бірақ дұрыс құралды пайдалансаңыз, онсыз да жасай аласыз!
Сұрау жоспары әдетте қандай болады? Мынадай нәрсе:
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
Онша емес.
Бірақ осылайша, қысқартылған түрденегізгі көрсеткіштерді ажыратқанда, бұл әлдеқайда анық:
Бірақ егер жоспар күрделірек болса, ол көмекке келеді пихерт уақытының таралуы түйіндер бойынша:
Ең қиын нұсқалар үшін ол көмектесуге асығады орындалу кестесі:
Мысалы, жоспардың бірнеше нақты түбірі болуы мүмкін өте маңызды емес жағдайлар бар:
Құрылымдық белгілер
Егер жоспардың бүкіл құрылымы мен оның ауырған жерлері қазірдің өзінде жасалып, көрініп тұрса, оларды әзірлеушіге неге ерекшелеп, «орыс тілінде» түсіндірмеске?
Біз бірнеше ондаған осындай ұсыныс үлгілерін жинадық.
Жол бойынша сұрау профильдері
Енді, егер сіз бастапқы сұрауды талданған жоспарға қоссаңыз, әрбір жеке мәлімдемеге қанша уақыт жұмсалғанын көре аласыз - келесідей:
...немесе тіпті келесідей:
Параметрлерді сұрауға ауыстыру
Егер сіз жоспарға сұранысты ғана емес, сонымен қатар журналдың DETAIL жолынан оның параметрлерін «тіркеген болсаңыз», оны опциялардың біріне қосымша көшіруге болады:
- сұраудағы мәнді ауыстыру арқылы
базаңызда тікелей орындау және одан әрі профильдеу үшінSELECT 'const', 'param'::text;
- PREPARE/EXECUTE арқылы мәнді алмастыру арқылы
параметрлік бөлікті елемеу мүмкін болғанда жоспарлаушының жұмысын эмуляциялау үшін - мысалы, бөлінген кестелерде жұмыс істегендеDEALLOCATE ALL; PREPARE q(text) AS SELECT 'const', $1::text; EXECUTE q('param'::text);
Жоспарлар мұрағаты
Қойыңыз, талдаңыз, әріптестеріңізбен бөлісіңіз! Жоспарлар мұрағатта қалады және оларға кейінірек оралуға болады:
Бірақ басқалардың сіздің жоспарыңызды көруін қаламасаңыз, «мұрағатқа жарияламау» ұяшығына құсбелгі қоюды ұмытпаңыз.
Келесі мақалаларда мен жоспарды талдау кезінде туындайтын қиындықтар мен шешімдер туралы айтатын боламын.
Ақпарат көзі: www.habr.com