Kartke tehingutest, mis toovad kaasa buffers...
Vaatame vĂ€ikese pĂ€ringu nĂ€itel mĂ”ned universaalsed lĂ€henemisviisid PostgreSQL pĂ€ringute optimeerimiseks. Kas neid kasutada vĂ”i mitte â otsustate teie, aga tundke need Ă€ra.
MĂ”nes hilisemates PG versioonides vĂ”ib olukord âtarkemaâ planeerijaga muutuda, kuid 9.4/9.6 puhul nĂ€eb see vĂ€lja enam-vĂ€hem sama, nagu siin nĂ€idatud.
VÔtan tÀiesti reaalse pÀringu:
SELECT
TRUE
FROM
"Dokument" d
INNER JOIN
"DokumentRakendus" doc_ex
USING("@Dokument")
INNER JOIN
"DokumendiTĂŒĂŒp" t_doc ON
t_doc."@DokumendiTĂŒĂŒp" = d."DokumendiTĂŒĂŒp"
WHERE
(d."Isik3" = 19091 or d."Töötaja" = 19091) AND
d."$Mustand" IS NULL AND
d."Kustutatud" IS NOT TRUE AND
doc_ex."Seisund"[1] IS TRUE AND
t_doc."DokumendiTĂŒĂŒp" = 'Tööplaan'
LIMIT 1; rÀÀkides tabelite ja vĂ€ljade nimedestVĂ”ib olla erinevaid arvamusi âveneâ nime kohta vĂ€ljadele ja tabelitele, aga see on maits kĂŒsimus. Kuna pole vĂ€lismaalasi arendajaid, ja PostgreSQL vĂ”imaldab meil nimetada isegi hieroglĂŒĂŒfidena, kui need on tsitaatides, siis eelistame nimetada objekte ĂŒheselt arusaadavalt, et ei tekiks segadust.
Vaatame saadud plaani:

144ms ja peaaegu 53K buffers â see tĂ€hendab rohkem kui 400MB andmeid! Ja meil on Ă”nne, kui kĂ”ik need on meie pĂ€ringu hetkeks vahemĂ€llu salvestatud, vastasel juhul venib see palju kauem, kui andmed tulevad kettalt.
Algoritm on kÔige tÀhtsam!
Kuidas iganes pÀringut optimeerida, tuleb esmalt mÔista, mida see tegelikult tegema peab.
JĂ€tame selle artikli raames andmebaasi struktuuri arendamise kĂ”rvale ja lepime kokku, et saame suhteliselt 'odavalt' pĂ€ringu ĂŒmber kirjutada ja/vĂ”i rakendada andmebaasi mĂ”ningaid vajalikke indekseid.
Nii et pÀring:
â kontrollib, kas mĂ”ni dokument eksisteerib
â Ă”iges olekus ja konkreetse tĂŒĂŒbi jĂ€rgi
â kus autor vĂ”i tĂ€itja on meie vajalik töötaja
JOIN + LIMIT 1
Sageli on arendajal lihtsam kirjutada pĂ€ring, kus esmalt tehakse suure hulga tabelite ĂŒhendamine, ja siis jÀÀb sellest hulgast ainult ĂŒksainus kirje. Aga arendaja jaoks lihtsam ei tĂ€henda, et see on andmebaasi jaoks efektiivsem.
Meie juhul oli tabeleid ainult 3 â aga milline efekt...
Alustame 'DokumendiTĂŒĂŒp' tabeliga ĂŒhenduse eemaldamisega ning ĂŒtleme andmebaasile, et meie korralduskirje tĂŒĂŒp on ainulaadne (me kĂŒll teame seda, kuid planeerija ei tunne veel Ă€ra):
WITH T AS (
SELECT
"@DokumendiTĂŒĂŒp"
FROM
"DokumendiTĂŒĂŒp"
WHERE
"DokumendiTĂŒĂŒp" = 'Tööplaan'
LIMIT 1
)
...
WHERE
d."DokumendiTĂŒĂŒp" = (TABLE T)
...Jah, kui tabel/CTE koosneb ainsast vÀljast ainsast kirjest, siis PG-s vÔib kirjutada isegi nii, selle asemel
d."DokumendiTĂŒĂŒp" = (SELECT "@DokumendiTĂŒĂŒp" FROM T LIMIT 1)PostgreSQL pĂ€ringutes 'laisk' arvutamine
BitmapOr vs UNION
MĂ”nes olukorras vĂ”ib Bitmap Heap Scan meile vĂ€ga kalliks minna â nĂ€iteks meie olukorras, kus piisavalt palju kirjeid langeb nĂ”utud tingimuse alla. Saime selle tĂ”ttu OR-tingimuse, mis muutus BitmapOr-operatsiooniks plaanis.
Naaseme algse ĂŒlesande juurde â peame leidma kirje, mis vastab ĂŒhele nendest tingimustest â st pole mĂ”tet otsida kĂ”iki 59K kĂ€mpingut mĂ”lema tingimuse jĂ€rgi. On viis, kuidas töötada vĂ€lja ĂŒks tingimus ja teise juurde minna ainult siis, kui esimesest ei leitud midagi.Meie abiks on selline konstruktsioon:
(
SELECT
...
LIMIT 1
)
UNION ALL
(
SELECT
...
LIMIT 1
)
LIMIT 1«VÀline» LIMIT 1 tagab, et otsing lÔpeb, kui esimene kirje leitakse. Ja kui see leitatakse juba esimeses blokis, siis teise tÀitmine ei toimu (never executed plaanis).
âPeidame CASE allaâ keerulised tingimused
Alguses lihtsas pĂ€ringus on ÀÀrmiselt ebamugav aspekt â kontrollimine seotud tabeli âDokumentRoskelikâ seisundi jĂ€rgi. ĂkskĂ”ik, kas muud tingimused vĂ€ljendis on tĂ”esed (nĂ€iteks, d.«Kustutatud» IS NOT TRUE), toimub see liitumine alati ja âkulutab ressursseâ. Rohkem vĂ”i vĂ€hem neid kulutatakse, sĂ”ltub selle tabeli mahust.
Kuid pÀringu saab muuta nii, et seotud kirje otsing toimub ainult siis, kui see on tÔesti vajalik:
SELECT
...
FROM
"Dokument" d
WHERE
...
/*index cond*/ AND
CASE
WHEN "$Mustand" IS NULL AND "Kustutatud" IS NOT TRUE THEN (
SELECT
"Seisund"[1] IS TRUE
FROM
"DokumentRoskelik"
WHERE
"@Dokument" = d."@Dokument"
)
END Kuna me ei vaja seotud tabelist ĂŒhtegi vĂ€lja , siis on meil vĂ”imalus muuta JOIN tingimuseks alampĂ€ringus.JĂ€tame indekseeritavad vĂ€ljad âkĂ”rgematesseâ CASE-i, lihtsad tingimused toome sisse WHEN-blokki â ja nĂŒĂŒd âraskeâ pĂ€ring tĂ€idetakse ainult juhul, kui liigume THEN-i.
Minu perekonnanimi on âKokkuvĂ”teâ
Kogume tulemuseks oleva pÀringu koos kÔigi eespool kirjeldatud mehhanismidega:
SOB5170
KUIDAS T ON KUIDAS (
VALIGE
"@DokumendiTĂŒĂŒp"
FROM
"DokumendiTĂŒĂŒp"
WHERE
"DokumendiTĂŒĂŒp" = 'Tööplaan'
)
(
VALIGE
TĂSI
FROM
"Dokument" d
WHERE
("Isik3", "DokumendiTĂŒĂŒp") = (19091, (TABEL T)) JA
JUHUL
KUI "$Mustandi" ON NULL JA "Kustutatud" EI OLE TĂSI SIIS (
VALIGE
"Seisund"[1] ON TĂSI
FROM
"DokumendiLaienemine"
WHERE
"@Dokument" = d."@Dokument"
)
OLE TINGIMUS
LIMIT 1
)
UNION ALL
(
VALIGE
TĂSI
FROM
"Dokument" d
WHERE
("DokumendiTĂŒĂŒp", "Töötaja") = ((TABEL T), 19091) JA
JUHUL
KUI "$Mustandi" ON NULL JA "Kustutatud" EI OLE TĂSI SIIS (
VALIGE
"Seisund"[1] ON TĂSI
FROM
"DokumendiLaienemine"
WHERE
"@Dokument" = d."@Dokument"
)
OLE TINGIMUS
LIMIT 1
)
LIMIT 1;Kohandame [vastu] indekseid
Kogenud pilk mĂ€rkis, et indekseeritud tingimused UNION allĂŒksustes erinevad veidi â see on tingitud sellest, et meil on juba vastavad indeksid tabelis. Ja kui neid ei oleks â siis oleks tasunud need luua: Dokument(Isik3, DokumendiTĂŒĂŒp) ja Dokument(DokumendiTĂŒĂŒp, Töötaja).
vÀljade jÀrjekorrast ROW-tingimustesPlaneerija vaatenurgast on muidugi vÔimalik kirjutada ka (A, B) = (constA, constB), ja (B, A) = (constB, constA). Kuid kirjutamisel indeksi vÀljade jÀrjekorras, on selline pÀring lihtsalt mugavam hiljem tÔrkeotsinguks.
Mida plaanis on?

Kahjuks ei olnud meil vedu ja esimeses UNION-blokis ei leitud midagi, seega teine ikkagi lĂ€ks tĂ€itmisele. Kuid isegi sel juhul â kokku 0.037ms ja 11 puhvrit!
Me kiirendasime pĂ€ringut ja vĂ€hendasime "andmete töötlemist" mĂ€lus mitme tuhande korra, kasutades piisavalt lihtsaid meetodeid â mitte halb tulemus vĂ€ikese kopeerimise kohta. đ
Allikas: habr.com
