Dasturchi o'zining DBA yoki biznes egasi PostgreSQL maslahatchisiga beradigan klassik savol deyarli har doim bir xil eshitiladi: "Nima uchun so'rovlar ma'lumotlar bazasida to'ldirilishi juda uzoq davom etadi?"
An'anaviy sabablar to'plami:
- samarasiz algoritm
bir necha o'n minglab yozuvlar ustida bir nechta CTE-ga QO'SHILishga qaror qilganingizda - eskirgan statistika
agar jadvaldagi ma'lumotlarning haqiqiy taqsimoti oxirgi marta ANALYZE tomonidan to'planganidan juda farq qilsa - resurslarga "ulang"
va endi protsessorning ajratilgan hisoblash quvvati etarli emas, gigabayt xotira doimiy ravishda pompalanadi yoki disk ma'lumotlar bazasining barcha "istaklarini" bajara olmaydi. - blokirovka qilish raqobat jarayonlaridan
Va agar blokirovkalarni ushlash va tahlil qilish juda qiyin bo'lsa, unda bizga kerak bo'lgan hamma narsa uchun so'rov rejasiyordamida olinishi mumkin
Ammo, xuddi shu hujjatlarda aytilganidek,
"Rejani tushunish - bu san'at va uni o'zlashtirish uchun ma'lum bir tajriba kerak ..."
Ammo agar siz to'g'ri vositadan foydalansangiz, u holda qila olasiz!
So'rov rejasi odatda qanday ko'rinishga ega? Shunga o'xshash narsa:
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
yoki shunga o'xshash:
"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"
Ammo "varaqdan" matndagi rejani o'qish juda qiyin va tushunarsiz:
- tugunda ko'rsatiladi pastki daraxt resurslari bo'yicha yig'indisi
ya'ni, ma'lum bir tugunni bajarish uchun qancha vaqt ketganini yoki jadvaldagi ushbu o'qish diskdan ma'lumotlarni qancha aniq ko'rsatganini tushunish uchun qandaydir tarzda birini boshqasidan ayirish kerak. - tugun vaqti kerak ilmoqlar bilan ko'paytiring
ha, ayirish "boshda" bajarilishi kerak bo'lgan eng murakkab operatsiya emas - axir, bajarish vaqti tugunning bitta bajarilishi uchun o'rtacha sifatida ko'rsatilgan va ularning yuzlablari bo'lishi mumkin. - yaxshi, va bularning barchasi birgalikda asosiy savolga javob berishimizga to'sqinlik qiladi - shuning uchun kim "eng zaif bo'g'in"?
Bularning barchasini bir necha yuz ishlab chiquvchilarimizga tushuntirishga harakat qilganimizda, tashqi tomondan bu shunday ko'rinishini angladik:
Va bu bizga kerak degan ma'noni anglatadi ...
asbob
Unda biz reja va so'rov bo'yicha "kim aybdor va nima qilish kerakligini" tushunishga yordam beradigan barcha asosiy mexanizmlarni to'plashga harakat qildik. Xo'sh, tajribangizning bir qismini hamjamiyat bilan baham ko'ring.
Tanishish va foydalanish -
Rejalarning ko'rinishi
Bunday ko'rinishda rejani tushunish osonmi?
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
Aslo emas.
Lekin shunday, qisqartirilgan shakldaasosiy ko'rsatkichlar ajratilganda, bu juda aniq:
Ammo agar reja yanada murakkab bo'lsa, u yordamga keladi piechart vaqtini taqsimlash tugunlar bo'yicha:
Xo'sh, eng qiyin variantlar uchun u yordam berishga shoshilmoqda taraqqiyot jadvali:
Masalan, reja bir nechta haqiqiy ildizga ega bo'lishi mumkin bo'lgan juda ahamiyatsiz holatlar mavjud:
Strukturaviy maslahatlar
Xo'sh, agar rejaning butun tuzilishi va uning zaif tomonlari allaqachon tuzilgan va ko'rinadigan bo'lsa, nega ularni ishlab chiquvchiga ta'kidlab, ularni "rus tilida" tushuntirmasligingiz kerak?
Biz allaqachon bir necha o'nlab bunday tavsiya shablonlarini to'plaganmiz.
Satr bo'yicha so'rov profili
Endi, agar siz tahlil qilingan rejaga asl so'rovni qo'shsangiz, har bir alohida bayonotga qancha vaqt sarflanganini ko'rishingiz mumkin - shunga o'xshash:
... yoki hatto shunday:
Parametrlarni so'rovga almashtirish
Agar siz nafaqat rejaga so'rovni, balki uning parametrlarini jurnalning DETAIL qatoridan "biriktirgan" bo'lsangiz, uni variantlardan biriga qo'shimcha ravishda nusxalashingiz mumkin:
- so'rovda qiymat almashtirish bilan
bazangizda to'g'ridan-to'g'ri bajarish va keyingi profillash uchunSELECT 'const', 'param'::text;
- PREPARE/EXECUTE orqali qiymat almashtirish bilan
parametrik qismni e'tiborsiz qoldirish mumkin bo'lganda rejalashtiruvchining ishiga taqlid qilish - masalan, bo'lingan jadvallar ustida ishlashdaDEALLOCATE ALL; PREPARE q(text) AS SELECT 'const', $1::text; EXECUTE q('param'::text);
Rejalar arxivi
Qo'ying, tahlil qiling, hamkasblar bilan baham ko'ring! Rejalar arxivda qoladi va ularga keyinroq qaytishingiz mumkin:
Ammo agar siz boshqalarga sizning rejangizni ko'rishini xohlamasangiz, "arxivda nashr qilmang" katagiga belgi qo'yishni unutmang.
Keyingi maqolalarda men rejani tahlil qilishda yuzaga keladigan qiyinchiliklar va qarorlar haqida gapiraman.
Manba: www.habr.com