EXPLAIN nima haqida sukut saqlaydi va uni qanday gapirish kerak

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 EXPLAIN operatori (Albatta, darhol tushuntirish (tahlil qilish, buferlar) yaxshiroq ...) yoki auto_explain moduli.

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:

EXPLAIN nima haqida sukut saqlaydi va uni qanday gapirish kerak

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 - tushuntirish.tensor.ru

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:

EXPLAIN nima haqida sukut saqlaydi va uni qanday gapirish kerak

Ammo agar reja yanada murakkab bo'lsa, u yordamga keladi piechart vaqtini taqsimlash tugunlar bo'yicha:

EXPLAIN nima haqida sukut saqlaydi va uni qanday gapirish kerak

Xo'sh, eng qiyin variantlar uchun u yordam berishga shoshilmoqda taraqqiyot jadvali:

EXPLAIN nima haqida sukut saqlaydi va uni qanday gapirish kerak

Masalan, reja bir nechta haqiqiy ildizga ega bo'lishi mumkin bo'lgan juda ahamiyatsiz holatlar mavjud:

EXPLAIN nima haqida sukut saqlaydi va uni qanday gapirish kerakEXPLAIN nima haqida sukut saqlaydi va uni qanday gapirish kerak

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?

EXPLAIN nima haqida sukut saqlaydi va uni qanday gapirish kerakBiz 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:

EXPLAIN nima haqida sukut saqlaydi va uni qanday gapirish kerak

... yoki hatto shunday:

EXPLAIN nima haqida sukut saqlaydi va uni qanday gapirish kerak

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 uchun

    SELECT '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 ishlashda

    DEALLOCATE 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: tushuntirish.tensor.ru/archive

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

a Izoh qo'shish