Profiler Query PostgreSQL: чӣ гуна мувофиқ кардани нақша ва дархост

Бисёре аз онҳое, ки аллакай истифода мебаранд izah.tensor.ru - хидмати визуализатсияи нақшаи PostgreSQL-и мо шояд аз яке аз қудратҳои бузурги он огоҳ набошад - табдил додани як порчаи барои хондан душвор дар гузориши сервер...

Profiler Query PostgreSQL: чӣ гуна мувофиқ кардани нақша ва дархост
... ба як дархости зебо тарҳрезишуда бо маслиҳатҳои контекстӣ барои гиреҳҳои нақшаи мувофиқ:

Profiler Query PostgreSQL: чӣ гуна мувофиқ кардани нақша ва дархост
Дар ин стенограммаи кисми дуюми у гузориш дар PGConf.Russia 2020 Ман ба шумо мегӯям, ки чӣ тавр мо ин корро карда тавонистем.

Транскрипти қисми аввал, ки ба мушкилоти маъмулии иҷрои дархостҳо ва роҳҳои ҳалли онҳо бахшида шудааст, дар мақола пайдо кардан мумкин аст "Рецептҳо барои дархостҳои бемори SQL".



Аввалан, биёед рангро оғоз кунем - ва мо дигар нақшаро ранг намекунем, мо онро аллакай ранг кардаем, мо онро аллакай зебо ва фаҳмо дорем, аммо дархост.

Ба назари мо чунин менамуд, ки бо чунин «варақ»-и форматнашуда дархосте, ки аз журнал гирифта шудааст, хеле зишт ва аз ин рӯ нороҳат менамояд.
Profiler Query PostgreSQL: чӣ гуна мувофиқ кардани нақша ва дархост

Хусусан вақте ки таҳиягарон дар як сатр қисми дархостро дар код (ин, албатта, антипаттерн аст, аммо ин рӯй медиҳад) "часпак" мекунанд. Даҳшатнок!

Биёед инро як навъ зеботар кашем.
Profiler Query PostgreSQL: чӣ гуна мувофиқ кардани нақша ва дархост

Ва агар мо метавонем онро зебо кашем, яъне қисмҳои асосии дархостро ба ҳам ҷудо кунем ва дубора якҷоя кунем, пас мо метавонем ба ҳар як объекти ин дархост як ишораро "часпонем" - он чизе ки дар нуқтаи мувофиқи нақша рӯй дод.

Дарахти синтаксиси дархост

Барои ин дархост аввал бояд таҳлил карда шавад.
Profiler Query PostgreSQL: чӣ гуна мувофиқ кардани нақша ва дархост

Зеро мо дорем асосии система дар NodeJS кор мекунад, пас мо барои он модул сохтем, шумо метавонед онро дар GitHub пайдо кунед. Дар асл, инҳо "пайвандҳои" васеъ ба дохили худи таҳлилгари PostgreSQL мебошанд. Яъне, грамматика танҳо дуӣ тартиб дода шудааст ва ба он аз NodeJS пайвандҳо сохта мешаванд. Мо модулҳои одамони дигарро ҳамчун асос гирифтем - дар ин ҷо ягон сирри калон нест.

Мо бадани дархостро ҳамчун вуруд ба функсияи худ ғизо медиҳем - дар натиҷа мо дарахти синтаксиси таҳлилшударо дар шакли объекти JSON мегирем.
Profiler Query PostgreSQL: чӣ гуна мувофиқ кардани нақша ва дархост

Акнун мо метавонем аз ин дарахт ба самти муқобил гузарем ва дархостро бо абзорҳо, рангҳо ва форматҳое, ки мо мехоҳем, ҷамъ оварем. Не, ин танзимшаванда нест, аммо ба назари мо чунин менамуд, ки ин қулай хоҳад буд.
Profiler Query PostgreSQL: чӣ гуна мувофиқ кардани нақша ва дархост

Харитасозии дархост ва гиреҳҳои нақша

Акнун биёед бубинем, ки чӣ тавр мо нақшаеро, ки дар қадами аввал таҳлил карда будем ва дархостеро, ки дар марҳилаи дуюм таҳлил кардем, муттаҳид карда метавонем.

Биёед як мисоли оддиро гирем - мо дархост дорем, ки CTE-ро тавлид мекунад ва аз он ду маротиба мехонад. Вай чунин планро тартиб медихад.
Profiler Query PostgreSQL: чӣ гуна мувофиқ кардани нақша ва дархост

CTE

Агар шумо ба он бодиққат нигоҳ кунед, то версияи 12 (ё аз он бо калимаи калидӣ сар карда MATERIALIZED) ташаккул CTE як монеаи мутлақ барои банақшагир аст.
Profiler Query PostgreSQL: чӣ гуна мувофиқ кардани нақша ва дархост

Ин маънои онро дорад, ки агар мо насли CTE дар ҷое дар дархост ва гиреҳ дар ҷое дар нақша мебинем CTE, пас ин гиреххо бешубха бо хамдигар «мубориза» мекунанд, мо онхоро фавран якчоя карда метавонем.

Мушкилот бо ситорача: CTE-ҳоро лона кардан мумкин аст.
Profiler Query PostgreSQL: чӣ гуна мувофиқ кардани нақша ва дархост
Хеле суст лона гузошта шудаанд ва ҳатто як ном доранд. Масалан, шумо метавонед дар дохили CTE A кунад CTE X, ва дар як сатҳ дар дохили CTE B боз кунед CTE X:

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

Ҳангоми муқоиса, шумо бояд инро дарк кунед. Фаҳмидани ин «бо чашмони худ» - ҳатто дидани нақша, ҳатто дидани матни дархост - хеле душвор аст. Агар насли CTE-и шумо мураккаб, лона дошта бошад ва дархостҳо калон бошанд, он комилан беҳуш аст.

ИТТИФОҚИ

Агар мо дар дархост калимаи калидӣ дошта бошем UNION [ALL] (оператори пайвастани ду намуна), пас дар нақша он ба ё гиреҳ мувофиқат мекунад Append, ё баъзе Recursive Union.
Profiler Query PostgreSQL: чӣ гуна мувофиқ кардани нақша ва дархост

Он чизе ки дар боло "боло" аст UNION - ин аввалин авлоди гиреҳи мост, ки "поён" аст - дуюм. Агар гузашт UNION мо якчанд блокро якбора «часпонда» дорем, пас Append-ҳанӯз танҳо як гиреҳ хоҳад буд, аммо он ду не, балки бисёр фарзанд хоҳад дошт - мувофиқи тартиби онҳо:

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

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

Мушкилот бо ситорача: дар дохили тавлиди намунаи рекурсивӣ (WITH RECURSIVE) инчунин метавонад зиёда аз як бошад UNION. Аммо танҳо блоки охирин пас аз охирин ҳамеша рекурсивӣ аст UNION. Ҳама чиз дар боло як аст, аммо гуногун UNION:

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

Шумо инчунин бояд ин гуна мисолҳоро «часпида» тавонед. Дар ин мисол мо мебинем UNION-Дар дархости мо 3 бахш буд. Мувофики он, як UNION мувофиқат мекунад Append- гиреҳ ва ба дигар - Recursive Union.
Profiler Query PostgreSQL: чӣ гуна мувофиқ кардани нақша ва дархост

Хондан-навиштан маълумот

Ҳама чиз тартиб дода шудааст, ҳоло мо медонем, ки кадом қисми дархост ба кадом қисми нақша мувофиқ аст. Ва дар ин порчаҳо мо метавонем ба осонӣ ва табиатан он ашёҳоеро пайдо кунем, ки "хондан" ҳастанд.

Аз нуқтаи назари пурсиш, мо намедонем, ки ин ҷадвал аст ё CTE, аммо онҳо аз ҷониби як гиреҳ таъин карда мешаванд RangeVar. Ва аз нуқтаи назари "хондан" ин инчунин маҷмӯи хеле маҳдуди гиреҳҳост:

  • 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]

Мо сохтори план ва дархостро медонем, мукотибаи блокхоро медонем, номи объектхоро медонем - як ба як мукоиса мекунем.
Profiler Query PostgreSQL: чӣ гуна мувофиқ кардани нақша ва дархост

Боз вазифаи "бо ситорача". Мо дархостро қабул мекунем, иҷро мекунем, мо ягон тахаллус надорем - мо онро танҳо ду маротиба аз ҳамон CTE мехонем.
Profiler Query PostgreSQL: чӣ гуна мувофиқ кардани нақша ва дархост

Мо ба накша назар меандозем — мушкилй дар чист? Чаро мо тахаллус доштем? Мо онро фармоиш надодаем. Чунин «рақами рақам»-ро аз куҷо пайдо мекунад?

PostgreSQL онро худаш илова мекунад. Шумо танҳо бояд инро фаҳмед маҳз ҳамин гуна тахаллус барои мо бо максади мукоиса бо план ягон маъно надорад, дар ин чо факат илова карда мешавад. Биёед ба ӯ аҳамият надиҳем.

Дуюм вазифаи "бо ситорача": агар мо аз ҷадвали тақсимшуда хонем, он гоҳ гиреҳ мегирем Append ё Merge Append, ки аз шумораи зиёди «бачагон» иборат хоханд буд ва хар кадоми онхо ба навъе хоханд буд Scan'om аз бахши ҷадвал: Seq Scan, Bitmap Heap Scan ё Index Scan. Аммо, дар ҳар сурат, ин "кӯдакон" дархостҳои мураккаб нахоҳанд буд - ҳамин тавр ин гиреҳҳоро аз онҳо фарқ кардан мумкин аст. Append Дар бораи мо UNION.
Profiler Query PostgreSQL: чӣ гуна мувофиқ кардани нақша ва дархост

Мо низ чунин гиреххоро мефахмем, онхоро «як туда» чамъ мекунем ва мегуем: «ҳар чизе ки шумо аз megatable мехонед, дар ин ҷо ва поёни дарахт аст".

Гиреҳҳои қабули маълумотҳои "оддӣ"

Profiler Query PostgreSQL: чӣ гуна мувофиқ кардани нақша ва дархост

Values Scan ба план мувофик аст VALUES дар дархост.

Result дархост бе он аст FROM Мисли SELECT 1. Ё вақте ки шумо изҳори дидаву дониста бардурӯғ доред WHERE-блок (пас атрибут пайдо мешавад 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 "харита" ба SRF-ҳои ҳамон ном.

Аммо бо дархостҳои лона ҳама чиз мураккабтар аст - мутаассифона, онҳо на ҳамеша ба онҳо табдил меёбанд InitPlan/SubPlan. Баъзан ба онҳо табдил меёбанд ... Join ё ... Anti Join, махсусан вақте ки шумо чизе монанди нависед WHERE NOT EXISTS .... Ва дар ин чо на хама вакт онхоро якчоя кардан мумкин аст — дар матни план ягон оператори ба узелхои план мувофик нест.

Боз вазифаи "бо ситорача": баъзе VALUES дар дархост. Дар ин ҳолат ва дар нақша шумо якчанд гиреҳ мегиред Values Scan.
Profiler Query PostgreSQL: чӣ гуна мувофиқ кардани нақша ва дархост

Суффиксҳои "рақамдор" барои фарқ кардани онҳо аз якдигар кӯмак мекунанд - онҳо маҳз бо тартиби пайдо шудани суффиксҳои мувофиқ илова карда мешаванд. VALUES-дар баробари дархост аз боло то поён блок мекунад.

Коркарди маълумот

Чунин ба назар мерасад, ки ҳама чиз дар дархости мо ҳал шудааст - ҳама чиз боқӣ мондааст Limit.
Profiler Query PostgreSQL: чӣ гуна мувофиқ кардани нақша ва дархост

Аммо дар ин ҷо ҳама чиз оддӣ аст - чунин гиреҳҳо Limit, Sort, Aggregate, WindowAgg, Unique "харитаи" як ба як ба операторҳои мувофиқ дар дархост, агар онҳо вуҷуд доранд. Дар ин чо ягон «ситора» ё душворй нест.
Profiler Query PostgreSQL: чӣ гуна мувофиқ кардани нақша ва дархост

ҶОЙҲО

Вақте ки мо якҷоя кардан мехоҳем, душвориҳо ба миён меоянд JOIN байни худ. Ин на ҳамеша имконпазир аст, аммо ин имконпазир аст.
Profiler Query PostgreSQL: чӣ гуна мувофиқ кардани нақша ва дархост

Аз нуқтаи назари таҳлилгари дархост, мо гиреҳ дорем JoinExpr, ки махз ду фарзанд дорад — чапу рост. Ин аст, мутаносибан, он чизест, ки "боло"-и JOIN-и шумост ва он чизе, ки дар дархост "зери" он навишта шудааст.

Ва аз нуктаи на-зари план ин ду насли баъзехо мебошанд * Loop/* Join- гиреҳ. Nested Loop, Hash Anti Join,... — хамин хел.

Биёед мантиқи оддиро истифода барем: агар мо ҷадвалҳои А ва В дошта бошем, ки дар нақша ҳамдигарро «пайваст» мекунанд, пас дар дархост онҳо метавонанд ё ҷойгир шаванд. A-JOIN-B, ё B-JOIN-A. Биёед кӯшиш кунем, ки ин тавр якҷоя кунем, биёед кӯшиш кунем, ки роҳи дигарро якҷоя кунем ва ғайра то он даме, ки чунин ҷуфтҳо тамом нашавад.

Биёед дарахти синтаксисиамонро гирем, нақшаамонро гирем, ба онҳо нигоҳ кунем... монанд нест!
Profiler Query PostgreSQL: чӣ гуна мувофиқ кардани нақша ва дархост

Биёед онро дар шакли графикҳо дубора кашем - оҳ, он аллакай ба чизе монанд аст!
Profiler Query PostgreSQL: чӣ гуна мувофиқ кардани нақша ва дархост

Биёед қайд кунем, ки мо гиреҳҳое дорем, ки ҳамзамон фарзандони B ва C доранд - ба мо аҳамият намедиҳад, ки бо кадом тартиб. Биёед онҳоро якҷоя кунем ва тасвири гиреҳро гардонем.
Profiler Query PostgreSQL: чӣ гуна мувофиқ кардани нақша ва дархост

Биёед бори дигар назар кунем. Ҳоло мо гиреҳҳо бо кӯдакони А ва ҷуфтҳо (B + C) дорем - бо онҳо низ мувофиқанд.
Profiler Query PostgreSQL: чӣ гуна мувофиқ кардани нақша ва дархост

Аҷоиб! Маълум мешавад, ки мо ин ду ҳастем JOIN аз су-пориш бо плану узелхо бомуваффакият якчоя карда шуданд.

Афсус, ки ин масъала на хамеша хал мешавад.
Profiler Query PostgreSQL: чӣ гуна мувофиқ кардани нақша ва дархост

Масалан, агар дар дархост A JOIN B JOIN C, ва дар план бошад, пеш аз хама гиреххои «берунй»-и А ва С васл карда шуданд.. Аммо дар дархост чунин оператор нест, мо чизе барои таъкид кардан, чизе барои ишора кардан надорем. Ҳангоми навиштан бо "вергул" ҳамин аст A, B.

Аммо, дар аксари ҳолатҳо, қариб ҳамаи гиреҳҳоро метавон "кушода" кард ва шумо метавонед ин намуди профилро дар тарафи чап сари вақт ба даст оред - айнан, ба монанди Google Chrome ҳангоми таҳлили коди JavaScript. Шумо мебинед, ки ҳар як сатр ва ҳар як изҳорот барои "иҷро кардан" чӣ қадар вақт лозим буд.
Profiler Query PostgreSQL: чӣ гуна мувофиқ кардани нақша ва дархост

Ва барои он ки барои шумо истифода бурдани ин ҳама қулайтар шавад, мо анборро сохтем бойгонӣ, ки дар он шумо метавонед нақшаҳои худро захира кунед ва дертар дар якҷоягӣ бо дархостҳои алоқаманд пайдо кунед ё истинодро бо касе мубодила кунед.

Агар ба шумо танҳо лозим аст, ки дархости хонданашавандаро ба шакли мувофиқ оваред, истифода баред "Нормалкунанда"-и мо.

Profiler Query PostgreSQL: чӣ гуна мувофиқ кардани нақша ва дархост

Манбаъ: will.com

Илова Эзоҳ