Kujdesi pĂ«r operacionet, bufferat qĂ« sjellinâŠ
Do tĂ« shqyrtojmĂ« disa qasje universale pĂ«r optimizimin e kĂ«rkesave nĂ« PostgreSQL pĂ«rmes njĂ« kĂ«rkese tĂ« vogĂ«l. TĂ« pĂ«rdoren ato apo jo â Ă«shtĂ« zgjedhja juaj, por ia vlen tĂ« jeni tĂ« informuar pĂ«r to.
Në ndonjë version të ardhshëm të PG, situata mund të ndryshojë me "inteligjencën" e planifikuesit, por për 9.4/9.6 ajo duket përafërsisht e njëjtë siç janë këtu shembujt.
Do të marrë një kërkesë mjaft reale:
SELECT
TRUE
FROM
"Dokument" d
INNER JOIN
"DokumentRrëfyes" doc_ex
USING("@Dokument")
INNER JOIN
"TipiDokumentit" t_doc ON
t_doc."@TipiDokumentit" = d."TipiDokumentit"
WHERE
(d."Lënda3" = 19091 or d."Punonjësi" = 19091) AND
d."$Kthimi" IS NULL AND
d."Fshier" IS NOT TRUE AND
doc_ex."Statusi"[1] IS TRUE AND
t_doc."TipiDokumentit" = 'PlanPunes'
LIMIT 1; për emrat e tabelave dhe fushaveNë lidhje me emrat "rusë" të fushave dhe tabelave, mund të keni mendime të ndryshme, por kjo është çështje shije. Pasi që nuk kemi zhvillues të huaj, dhe PostgreSQL na lejon të jepni emra madje edhe me hieroglifë, për sa kohë që janë të rrethuara me thonjëza, ne preferojmë të emërojmë objektet në mënyrë të qartë dhe të kuptueshme, në mënyrë që të mos ketë keqkuptime.
Le të shohim planin e marrë:

144ms dhe gati 53K buffer â do tĂ« thotĂ« mĂ« shumĂ« se 400MB tĂ« dhĂ«nash! Dhe do tĂ« kemi fat nĂ«se tĂ« gjitha ato do tĂ« ishin nĂ« cache nĂ« momentin e kĂ«rkesĂ«s tonĂ«, pĂ«rndryshe ajo do tĂ« zgjasĂ« disa herĂ« mĂ« gjatĂ« kur tĂ« lexojmĂ« nga disku.
Algoritmi është më i rëndësishëm se gjithçka!
Për të optimizuar ndonjë kërkesë, së pari duhet të kuptojmë çfarë duhet të bëjë ajo.
Të lëmë jashtë kësaj artikulli zhvillimin e strukturës së DB-së, dhe të pajtohemi që ne mund ta riformatojmë kërkesën dhe/ose të aplikojmë disa indekse.
Kështu, kërkesa:
â kontrollon ekzistencĂ«n e ndonjĂ« dokumenti
â nĂ« gjendjen e nevojshme dhe tĂ« njĂ« tipi tĂ« caktuar
â ku autori ose realizuesi Ă«shtĂ« punonjĂ«si ynĂ« i nevojshĂ«m
JOIN + LIMIT 1
ShpeshherĂ«, zhvilluesit e preferojnĂ« tĂ« shkruajnĂ« njĂ« kĂ«rkesĂ« ku fillimisht lidhen shumĂ« tabela, dhe pastaj nga gjithĂ« ato mbetet vetĂ«m njĂ« regjistrim. Por mĂ« e lehta pĂ«r zhvilluesin â nuk do tĂ« thotĂ« mĂ« efektive pĂ«r DB-nĂ«.
NĂ« rastin tonĂ« kishte vetĂ«m 3 tabela â dhe çfarĂ« efektiâŠ
Le të fillojmë duke eliminuar lidhjen me tabelën "TipDokumenti", ndërkohë që i tregojmë DB-së se regjistrimi i tipit tonë është unik (ne e dimë, por planifikuesi ende nuk e ka kuptuar):
ME T SI (
ZGJIDHJA
"@LlojiDokumentit"
NGA
"LlojiDokumentit"
KU
"LlojiDokumentit" = 'Plani i Punës'
KUFIZO 1
)
...
KU
d."LlojiDokumentit" = (TABELA T)
...Po, nëse tabela/CTE përbëhet nga një fushë e vetme me një regjistër vetëm, mund ta shkruajmë edhe kështu në PG, në vend të
d."LlojiDokumentit" = (ZGJIDH "@LlojiDokumentit" NGA T KUFIZO 1)Llogaritjet «lenjase» në kërkesat PostgreSQL
BitmapOr vs UNION
NĂ« disa raste, Bitmap Heap Scan do tĂ« na kushtojĂ« shumĂ« â pĂ«r shembull, nĂ« situatĂ«n tonĂ«, ku mjaft regjistra bien nĂ«n kushtin e kĂ«rkuar. E kemi marrĂ« kĂ«tĂ« pĂ«r shkak tĂ« kushtit OR, i transformuar nĂ« BitmapOr-operimin nĂ« plan.
Le tĂ« kthehemi te detyra fillestare â duhet tĂ« gjejmĂ« regjistrin qĂ« i pĂ«rgjigjet ndonjĂ«rit nga kushtet â do tĂ« thotĂ« nuk ka nevojĂ« tĂ« kĂ«rkojmĂ« tĂ« gjitha 59K regjistrat pĂ«r tĂ« dy kushtet. Ekziston njĂ« mĂ«nyrĂ« pĂ«r tĂ« pĂ«rfunduar njĂ« kusht, dhe pĂ«r tĂ« kaluar te tjetri vetĂ«m kur pĂ«r tĂ« parin nuk gjendet asgjĂ«. NjĂ« konstrukcion i tillĂ« do na ndihmojĂ«:
(
ZGJIDHJA
...
KUFIZO 1
)
UNION ALL
(
ZGJIDHJA
...
KUFIZO 1
)
KUFIZO 1LIMIT 1 garanton që kërkimi do të mbyllet sapo të gjendet regjistri i parë. Dhe nëse ai gjendet në blokun e parë, ekzekutimi i dytë nuk do të kryhet (nuk ekzekutohet kurrë në plan).
«Fshehim nën CASE» kushtet e komplikuara
NjĂ« moment shumĂ« i pakĂ«ndshĂ«m nĂ« kĂ«rkesĂ«n origjinale Ă«shtĂ« kontrolli i gjendjes nĂ« tabelĂ«n e lidhur «DokumentZgjerimi». PavarĂ«sisht nga vĂ«rtetĂ«sia e kushteve tĂ« tjera nĂ« shprehje (pĂ«r shembull, d.«Fshirë» NUK ĂSHTĂ E VERTETĂ), ky lidhje kryhet gjithmonĂ« dhe «kushton burime». MĂ« shumĂ« ose mĂ« pak do tĂ« shpenzohen - varet nga volumi i kĂ«saj tabele.
Por mund të modifikojmë kërkesën në mënyrë që kërkimi i regjistrit të lidhur të ndodhte vetëm kur kjo është në të vërtetë e nevojshme:
SELECT
...
FROM
"Dokument" d
WHERE
... /*kusht index*/ DHE
CASE
KUR "$Draft" ĂSHTĂ NULL DHE "FshirĂ«" NUK ĂSHTĂ E VERTETĂ ATĂHERĂ (
SELECT
"Gjendja"[1] ĂSHTĂ E VERTETĂ
FROM
"DokumentZgjerimi"
WHERE
"@Dokument" = d."@Dokument"
)
FUND Pasi nga tabela e lidhur nuk na duhen asnjë nga fushat, atëherë kemi mundësinë ta kthejmë JOIN në kusht sipas nënkërkese.
LĂ«rini fushat e indeksuara «jashtë» CASE, kushtet e thjeshta i pĂ«rfshijmĂ« nĂ« bllokun WHEN â dhe tani kĂ«rkesa «e rĂ«ndë» ekzekutohet vetĂ«m kur kalojmĂ« nĂ« THEN.
Mënyra ime «Të gjitha»
Krijojmë kërkesën përfundimtare me të gjitha mekanizmat e përshkruar më sipër:
ME T SI (
ZGJIDH
"@TipiDokumenti"
NGA
"TipiDokumentit"
KU
"TipiDokumentit" = 'Plani i Punës'
)
(
ZGJIDH
E VERTETĂ
NGA
"Dokumenti" d
KU
("Persona3", "TipiDokumentit") = (19091, (TABELA T)) DHE
RASTI
KUR "$Draft" ĂSHTE NULL DHE "FshirĂ«" NUK ĂSHTE E VERTETĂ atĂ«herĂ« (
ZGJIDH
"Gç¶æ"[1] ĂSHTE E VERTETĂ
NGA
"DokumentiZgjatje"
KU
"@Dokumenti" = d."@Dokumenti"
)
FUND
KUFIZO 1
)
BASHKOHUNI TĂ GJITHA
(
ZGJIDH
E VERTETĂ
NGA
"Dokumenti" d
KU
("TipiDokumentit", "Punonjësi") = ((TABELA T), 19091) DHE
RASTI
KUR "$Draft" ĂSHTE NULL DHE "FshirĂ«" NUK ĂSHTE E VERTETĂ atĂ«herĂ« (
ZGJIDH
"Gç¶æ"[1] ĂSHTE E VERTETĂ
NGA
"DokumentiZgjatje"
KU
"@Dokumenti" = d."@Dokumenti"
)
FUND
KUFIZO 1
)
KUFIZO 1;Përshtatëm [për] indeksat
Syri i zakonshĂ«m vuri re se kushtet e indeksuara nĂ« nĂ«nblloqet UNION pak ndryshojnĂ« â kjo Ă«shtĂ« sepse tashmĂ« kemi indeksat e duhur nĂ« tabelĂ«. NĂ«se nuk do tĂ« kishte, atĂ«herĂ« do tĂ« ishte e nevojshme tĂ« krijohej: Dokumenti(Faqe3, LlojiDokumentit) dhe Dokumenti(LlojiDokumentit, PunonjĂ«si).
rreth rendit të fushave në kushtet ROWSipas planifikuesit, natyrisht, mund të shkruhet dhe (A, B) = (constA, constB), dhe (B, A) = (constB, constA). Por gjatë regjistrimit në rendin e fushave në indeks, një kërkesë e tillë është thjesht më e lehtë për debug.
ĂfarĂ« ka nĂ« plan?

FatkeqĂ«sisht, nuk patĂ«m fat, dhe nĂ« bllokun e parĂ« UNION nuk u gjet asgjĂ«, prandaj i dyti ndoqi megjithatĂ« pĂ«r ekzekutim. Por edhe kĂ«shtu â vetĂ«m 0.037ms dhe 11 buffers!
Ne rritĂ«m shpejtĂ«sinĂ« e kĂ«rkesĂ«s dhe reduktuam "shkarkimin" e tĂ« dhĂ«nave nĂ« memorie nĂ« disa mijĂ«ra herĂ«, duke pĂ«rdorur metoda mjaft tĂ« thjeshta â njĂ« rezultat i shkĂ«lqyer pĂ«r njĂ« kopje tĂ« vogĂ«l. đ
Burimi: habr.com
