PostgreSQL Query Profiler: Plan və sorğunu necə uyğunlaşdırmaq olar

Artıq istifadə edən çoxları izah.tensor.ru - PostgreSQL planının vizuallaşdırılması xidmətimiz onun super güclərindən birinin fərqində olmaya bilər - server jurnalının oxunması çətin olan hissəsini çevirmək ...

PostgreSQL Query Profiler: Plan və sorğunu necə uyğunlaşdırmaq olar
... müvafiq plan qovşaqları üçün kontekstli göstərişlərlə gözəl tərtib edilmiş sorğuya:

PostgreSQL Query Profiler: Plan və sorğunu necə uyğunlaşdırmaq olar
Onun ikinci hissəsinin bu stenoqramında PGConf.Russia 2020-də hesabat Bunu necə bacardığımızı sizə deyəcəyəm.

Tipik sorğu performansı problemlərinə və onların həllinə həsr olunmuş birinci hissənin transkripti məqalədə tapıla bilər. "Xəstə SQL sorğuları üçün reseptlər".



Birincisi, rəngləmə edək - və biz artıq planı rəngləməyəcəyik, biz artıq rəngləmişik, artıq gözəl və başa düşüləndir, lakin xahiş.

Bizə elə gəldi ki, formatlaşdırılmamış "vərəq" ilə jurnaldan çıxarılan sorğu çox çirkin və buna görə də əlverişsiz görünür.
PostgreSQL Query Profiler: Plan və sorğunu necə uyğunlaşdırmaq olar

Xüsusilə tərtibatçılar koddakı sorğu orqanını bir sətirdə "yapışdırdıqda" (əlbəttə ki, bu, anti-naxışdır, lakin olur). Dəhşət!

Gəlin onu birtəhər daha gözəl çəkək.
PostgreSQL Query Profiler: Plan və sorğunu necə uyğunlaşdırmaq olar

Əgər onu gözəl şəkildə çəkə bilsək, yəni sorğu gövdəsini söküb geri yığa bilsək, o zaman bu sorğunun hər bir obyektinə - planın müvafiq nöqtəsində baş verənlərə işarə "əlavə edə" bilərik.

Sorğu Sintaksis Ağacı

Bunun üçün ilk öncə sorğu təhlil edilməlidir.
PostgreSQL Query Profiler: Plan və sorğunu necə uyğunlaşdırmaq olar

Çünki, bizdə var sistemin nüvəsi NodeJS-də işləyir, sonra bunun üçün bir modul etdik, edə bilərsiniz github-da tapın. Əslində bunlar PostgreSQL analizatorunun daxili hissələrinə genişlənmiş "bağlamalardır". Yəni, qrammatika sadəcə olaraq ikili tərtib edilir və ona bağlamalar NodeJS tərəfindən edilir. Başqalarının modullarını əsas götürdük - burada böyük bir sirr yoxdur.

Giriş sorğusunun gövdəsini funksiyamıza qidalandırırıq - çıxışda JSON obyekti şəklində təhlil edilmiş sintaksis ağacı alırıq.
PostgreSQL Query Profiler: Plan və sorğunu necə uyğunlaşdırmaq olar

İndi biz bu ağacdan əks istiqamətdə keçib, istədiyimiz abzaslar, rəngləmə, formatlaşdırma ilə sorğunu yığa bilərik. Xeyr, bu konfiqurasiya edilə bilməz, amma bunun rahat olacağını düşündük.
PostgreSQL Query Profiler: Plan və sorğunu necə uyğunlaşdırmaq olar

Xəritə Sorğusu və Plan Düyünləri

İndi gəlin birinci addımda təhlil etdiyimiz planı və ikinci mərhələdə təhlil etdiyimiz sorğunu necə birləşdirə biləcəyimizi görək.

Sadə bir nümunə götürək - bizdə CTE təşkil edən və onu iki dəfə oxuyan bir sorğu var. O, belə bir plan yaradır.
PostgreSQL Query Profiler: Plan və sorğunu necə uyğunlaşdırmaq olar

CTE

Diqqətlə baxsanız, 12-ci versiyadan əvvəl (və ya açar sözü ilə ondan başlayaraq MATERIALIZED) formalaşması CTE planlaşdırıcı üçün qeyd-şərtsiz maneədir.
PostgreSQL Query Profiler: Plan və sorğunu necə uyğunlaşdırmaq olar

Və bu o deməkdir ki, əgər sorğunun bir yerində CTE-nin nəslini və planın bir yerində qovşağı görsək CTE, onda bu qovşaqlar öz aralarında unikal şəkildə "döyüşür", biz onları dərhal birləşdirə bilərik.

"Ulduz işarəsi ilə" tapşırığıQeyd: CTE-lər yuvalana bilər.
PostgreSQL Query Profiler: Plan və sorğunu necə uyğunlaşdırmaq olar
Çox zəif yuvalanmış və hətta eyni ad var. Məsələn, içəridə edə bilərsiniz CTE A etmək CTE X, və içəridə eyni səviyyədə CTE B yenidən et CTE X:

WITH A AS (
  WITH X AS (...)
  SELECT ...
)
, B AS (
  WITH X AS (...)
  SELECT ...
)
...

Müqayisə edərkən bunu başa düşməlisiniz. Bunu "gözlərlə" başa düşmək çox çətindir - hətta planı görmək, hətta tələbin gövdəsini görmək. Əgər CTE nəsliniz mürəkkəbdirsə, iç-içədirsə, sorğular böyükdürsə, o, tamamilə şüursuzdur.

UNION

Əgər sorğuda açar sözümüz varsa UNION [ALL] (iki nümunəni birləşdirən operator), onda o, planda ya node ilə uyğun gəlir Append, və ya bəziləri Recursive Union.
PostgreSQL Query Profiler: Plan və sorğunu necə uyğunlaşdırmaq olar

"Yuxarıda" olan UNION - bu, "aşağıdan" olan nodeumuzun ilk övladıdır - ikinci. Əgər keçsə UNION biz bir anda bir neçə bloku "yapışdırdıq" Append-qovşağın hələ də yalnız bir övladı olacaq, lakin onun iki deyil, çoxlu uşağı olacaq - müvafiq olaraq sıra ilə:

  (...) -- #1
UNION ALL
  (...) -- #2
UNION ALL
  (...) -- #3

Append
  -> ... #1
  -> ... #2
  -> ... #3

"Ulduz işarəsi ilə" tapşırığı: daxili rekursiv gətirmə nəsli (WITH RECURSIVE) birdən çox ola bilər UNION. Ancaq sonuncu blokdan sonra yalnız sonuncu blok həmişə rekursivdir UNION. Yuxarıdakı hər şey birdir, lakin fərqlidir UNION:

WITH RECURSIVE T AS(
  (...) -- #1
UNION ALL
  (...) -- #2, тут кончается генерация стартового состояния рекурсии
UNION ALL
  (...) -- #3, только этот блок рекурсивный и может содержать обращение к T
)
...

Belə nümunələri də “yapışdırmağı” bacarmaq lazımdır. Bu nümunədə biz bunu görürük UNION-istəyimizdə seqmentlər 3 ədəd idi. Müvafiq olaraq, bir UNION uyğun gəlir Append- düyün, digəri - Recursive Union.
PostgreSQL Query Profiler: Plan və sorğunu necə uyğunlaşdırmaq olar

Oxu-yazma məlumatları

Hər şey, qoyulmuşdur, indi sorğunun hansı hissəsinin planın hansı hissəsinə uyğun olduğunu bilirik. Və bu parçalarda biz asanlıqla və təbii olaraq “oxunan” obyektləri tapa bilərik.

Sorğu nöqteyi-nəzərindən bunun cədvəl və ya CTE olduğunu bilmirik, lakin onlar eyni qovşaq ilə işarələnir. RangeVar. Və "oxunan" planda bu da kifayət qədər məhdud qovşaqlar dəstidir:

  • Seq Scan on [tbl]
  • Bitmap Heap Scan on [tbl]
  • Index [Only] Scan [Backward] using [idx] on [tbl]
  • CTE Scan on [cte]
  • Insert/Update/Delete on [tbl]

Biz planın və sorğunun strukturunu bilirik, blokların yazışmalarını bilirik, obyektlərin adlarını bilirik - birmənalı müqayisə aparırıq.
PostgreSQL Query Profiler: Plan və sorğunu necə uyğunlaşdırmaq olar

Yenidən "ulduz ilə" tapşırığı. Bir sorğu qəbul edirik, icra edirik, heç bir ləqəbimiz yoxdur - bir CTE-dən iki dəfə oxuyuruq.
PostgreSQL Query Profiler: Plan və sorğunu necə uyğunlaşdırmaq olar

Gəlin plana baxaq - problem nədir? Niyə bizim ləqəbimiz var idi? Biz sifariş etməmişik. O, belə “nömrə”ni haradan alır?

PostgreSQL onu özü əlavə edir. Sadəcə bunu başa düşmək lazımdır məhz belə bir ləqəb bizim üçün planla müqayisə məqsədi ilə bunun heç bir mənası yoxdur, sadəcə olaraq bura əlavə olunur. Ona fikir verməyək.

İkinci "ulduz ilə" tapşırığı: bölünmüş cədvəldən oxuyuruqsa, onda bir qovşaq alacağıq Append və ya Merge Append, çoxlu sayda "uşaqlardan" ibarət olacaq və hər biri bir neçə olacaq Scan'om masa bölməsindən: Seq Scan, Bitmap Heap Scan və ya Index Scan. Ancaq hər halda, bu "uşaqlar" mürəkkəb sorğular olmayacaq - bu qovşaqları belə ayırd etmək olar. Append da UNION.
PostgreSQL Query Profiler: Plan və sorğunu necə uyğunlaşdırmaq olar

Biz də belə düyünləri başa düşürük, onları “bir yığında” yığırıq və deyirik: “megatable-dan oxuduğunuz hər şey burada və ağacın altındadır".

"Sadə" Məlumat Alma Qovşaqları

PostgreSQL Query Profiler: Plan və sorğunu necə uyğunlaşdırmaq olar

Values Scan planda uyğun gəlir VALUES sorğuda.

Result olmayan bir xahişdir FROM kimi SELECT 1. Yaxud yanlış ifadəniz olduqda WHERE-blok (sonra atribut görünür One-Time Filter):

EXPLAIN ANALYZE
SELECT * FROM pg_class WHERE FALSE; -- или 0 = 1

Result  (cost=0.00..0.00 rows=0 width=230) (actual time=0.000..0.000 rows=0 loops=1)
  One-Time Filter: false

Function Scan Eyni adlı SRF-də "Mapyatsya".

Ancaq iç-içə sorğularla hər şey daha mürəkkəbdir - təəssüf ki, onlar həmişə sorğulara çevrilmir. InitPlan/SubPlan. Bəzən çevrilirlər ... Join və ya ... Anti Join, xüsusilə kimi bir şey yazdığınız zaman WHERE NOT EXISTS .... Orada birləşdirmək həmişə mümkün deyil - planın mətnində planın qovşaqlarına uyğun operatorlar yoxdur.

Yenidən "ulduz ilə" tapşırığı: bəziləri VALUES sorğuda. Bu vəziyyətdə və planda bir neçə qovşaq əldə edəcəksiniz Values Scan.
PostgreSQL Query Profiler: Plan və sorğunu necə uyğunlaşdırmaq olar

"Nömrə" şəkilçiləri onları bir-birindən ayırmağa kömək edəcək - bu, uyğun gələn ardıcıllıqla əlavə olunur. VALUES-sorğunun gedişində yuxarıdan aşağıya doğru bloklar.

Verilənlərin emalı

Deyəsən, sorğumuzda hər şey qaydasındadır - yalnız Limit.
PostgreSQL Query Profiler: Plan və sorğunu necə uyğunlaşdırmaq olar

Ancaq burada hər şey sadədir - bu cür qovşaqlar Limit, Sort, Aggregate, WindowAgg, Unique Əgər onlar varsa, sorğuda müvafiq operatorlarla təkbətək “xəritə” edirlər. Heç bir "ulduzlar" və heç bir çətinlik yoxdur.
PostgreSQL Query Profiler: Plan və sorğunu necə uyğunlaşdırmaq olar

OL

Birləşdirmək istədiyimiz zaman çətinliklər yaranır JOIN öz aralarında. Bu həmişə mümkün deyil, lakin mümkündür.
PostgreSQL Query Profiler: Plan və sorğunu necə uyğunlaşdırmaq olar

Sorğu təhlilçisinin nöqteyi-nəzərindən bir qovşağımız var JoinExpr, tam iki uşağı var - sol və sağ. Bu, müvafiq olaraq, sizin JOIN-in “yuxarısında” və sorğuda “altında” yazılanlardır.

Və plan baxımından bunlar bəzilərinin iki nəslindəndir * Loop/* Join-düyün. Nested Loop, Hash Anti Join... belə bir şeydir.

Sadə məntiqdən istifadə edək: planda bir-birinə “birləşən” A və B cədvəllərimiz varsa, sorğuda onlar ya yerləşə bilər. A-JOIN-BVə ya B-JOIN-A. Gəlin belə birləşdirməyə çalışaq, əks şəkildə birləşdirməyə çalışaq və belə cütlər bitənə qədər davam edək.

Sintaksis ağacımızı götür, planımızı götür, onlara bax... belə görünmür!
PostgreSQL Query Profiler: Plan və sorğunu necə uyğunlaşdırmaq olar

Gəlin onu qrafiklər şəklində yenidən çəkək - oh, bir şey artıq bir şeyə bənzəyir!
PostgreSQL Query Profiler: Plan və sorğunu necə uyğunlaşdırmaq olar

Diqqət yetirək ki, eyni zamanda B və C uşaqları olan qovşaqlarımız var - hansı ardıcıllıqla bizim üçün fərqi yoxdur. Gəlin onları birləşdirək və node şəklini çevirək.
PostgreSQL Query Profiler: Plan və sorğunu necə uyğunlaşdırmaq olar

Yenidən baxaq. İndi A uşaqları və cütləri (B + C) olan qovşaqlarımız var - onlarla uyğun gəlir.
PostgreSQL Query Profiler: Plan və sorğunu necə uyğunlaşdırmaq olar

Əla! Belə çıxır ki, biz bu ikiliyik JOIN sorğudan planın qovşaqları ilə uğurla birləşdirildi.

Təəssüf ki, bu problem həmişə həll edilmir.
PostgreSQL Query Profiler: Plan və sorğunu necə uyğunlaşdırmaq olar

Məsələn, əgər sorğu A JOIN B JOIN C, və planda ilk növbədə A və C "ekstremal" qovşaqları birləşdirildi.Ancaq sorğuda belə operator yoxdur, vurğulamaq üçün heç bir şeyimiz yoxdur, işarəni bağlayacaq heç nə yoxdur. Yazdığınız zaman "vergül" ilə eynidir A, B.

Ancaq əksər hallarda, demək olar ki, bütün qovşaqlar "açmağı" və vaxtında solda belə bir profil əldə etməyi bacarır - sözün əsl mənasında, Google Chrome-da olduğu kimi, JavaScript kodunu təhlil edərkən. Hər bir sətir və hər bir ifadənin nə qədər "icra edildiyini" görə bilərsiniz.
PostgreSQL Query Profiler: Plan və sorğunu necə uyğunlaşdırmaq olar

Və bütün bunlardan istifadə etməyinizi asanlaşdırmaq üçün biz yaddaş saxladıq arxivi, burada saxlaya və sonra planlarınızı əlaqəli sorğularla birlikdə tapa və ya kimsə ilə link paylaşa bilərsiniz.

Əgər sadəcə oxunmayan sorğunu adekvat formaya gətirmək lazımdırsa, istifadə edin bizim "normalizatorumuz".

PostgreSQL Query Profiler: Plan və sorğunu necə uyğunlaşdırmaq olar

Mənbə: www.habr.com

Добавить комментарий