Dagoeneko 6000 aldiz baino gehiago erabili duzu, baina oharkabean pasa daitekeen funtzio erabilgarri bat da egiturazko arrastoak, hau bezalako itxura dutenak:
Entzun itzazu, eta zure eskaerak "leun eta zetatsu bihurtuko dira". π
Baina serioski, eskaera bat motel eta baliabide gose egiten duten egoera asko tipikoak dira eta planaren egituraren eta datuen arabera antzeman daitezke.
Kasu honetan, garatzaile bakoitzak ez du bere kabuz optimizazio-aukerarik bilatu behar, bere esperientzian soilik oinarrituz - hemen gertatzen ari dena esan dezakegu, zein izan daitekeen arrazoia eta konponbide bati nola heldu. Horixe egin genuen.
Ikus ditzagun kasu hauek hurbilagotik: nola definitzen diren eta zer gomendiotara eramaten duten.
Gaian hobeto murgiltzeko, lehenik eta behin dagokion blokea entzun dezakezu Nire txostena PGConf.Russia 2020-n, eta gero bakarrik adibide bakoitzaren azterketa zehatza egitera pasa:
#1: indizea "gutxietsia"
Sortzen denean
Erakutsi "LLC Kolokolchik" bezeroaren azken faktura.
Halako lagin primitibo batean ere - 8.5 aldiz azkarragoa eta 33 aldiz irakurketa gutxiago. Zenbat eta "gertaera" gehiago izan balio bakoitzeko, orduan eta nabariagoa izango da eragina fk.
Kontuan izan dut indize horrek "aurrizkia" indize gisa funtzionatuko duela lehen baino okerrago beste kontsultetarako fk, non ordenatu pk ez zegoen eta ez dago (honi buruz gehiago irakur dezakezu Eraginkortasunik gabeko indizeak aurkitzeari buruzko nire artikuluan). Barne, normal emango du atzerriko gakoen laguntza esplizitua eremu honetan.
#2: indize-ebakidura (BitmapAnd)
Sortzen denean
Erakutsi "LLC Kolokolchik" bezeroarentzako akordio guztiak, "NAO Buttercup"-en izenean egindakoak.
Nola identifikatu
-> BitmapAnd
-> Bitmap Index Scan
-> Bitmap Index Scan
Gomendioak
sortzen indize konposatua jatorrizko bi eremuen arabera edo lehendik daudenetako bat zabaldu bigarreneko eremuekin.
Adibidea:
CREATE TABLE tbl AS
SELECT
generate_series(1, 100000) pk -- 100K "ΡΠ°ΠΊΡΠΎΠ²"
, (random() * 100)::integer fk_org -- 100 ΡΠ°Π·Π½ΡΡ Π²Π½Π΅ΡΠ½ΠΈΡ ΠΊΠ»ΡΡΠ΅ΠΉ
, (random() * 1000)::integer fk_cli; -- 1K ΡΠ°Π·Π½ΡΡ Π²Π½Π΅ΡΠ½ΠΈΡ ΠΊΠ»ΡΡΠ΅ΠΉ
CREATE INDEX ON tbl(fk_org); -- ΠΈΠ½Π΄Π΅ΠΊΡ Π΄Π»Ρ foreign key
CREATE INDEX ON tbl(fk_cli); -- ΠΈΠ½Π΄Π΅ΠΊΡ Π΄Π»Ρ foreign key
SELECT
*
FROM
tbl
WHERE
(fk_org, fk_cli) = (1, 999); -- ΠΎΡΠ±ΠΎΡ ΠΏΠΎ ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½ΠΎΠΉ ΠΏΠ°ΡΠ΅
(
SELECT
*
FROM
tbl
WHERE
fk_own = 1 -- ΡΠ½Π°ΡΠ°Π»Π° "ΡΠ²ΠΎΠΈ" 20
ORDER BY
pk
LIMIT 20
)
UNION ALL
(
SELECT
*
FROM
tbl
WHERE
fk_own IS NULL -- ΠΏΠΎΡΠΎΠΌ "Π½ΠΈΡΡΠΈ" 20
ORDER BY
pk
LIMIT 20
)
LIMIT 20; -- Π½ΠΎ Π²ΡΠ΅Π³ΠΎ - 20, Π±ΠΎΠ»ΡΡΠ΅ ΠΈ Π½Π΅ Π½Π°Π΄ΠΎ
Beharrezko 20 erregistro guztiak lehen blokean berehala jaso zirela aprobetxatu genuen, beraz, bigarrena, Bitmap Heap Scan "garestiago"arekin, ez zen exekutatu ere egin - azkenean. 22 aldiz azkarragoa, 44 aldiz irakurketa gutxiago!
Sortu [gehiago] espezializatua NON baldintza duen indizea edo gehitu eremu gehigarriak aurkibidean.
Iragazkiaren egoera "estatikoa" bada zure helburuetarako, hau da ez du hedapena suposatzen baloreen zerrenda etorkizunean - hobe da NON indizea erabiltzea. Hainbat egoera boolear/enumeratu ondo sartzen dira kategoria honetan.
Iragazte-baldintza bada esanahi desberdinak har ditzake, orduan hobe da indizea eremu hauekin zabaltzea - ββgoiko BitmapAnd-ekin gertatzen den bezala.
Adibidea:
CREATE TABLE tbl AS
SELECT
generate_series(1, 100000) pk -- 100K "ΡΠ°ΠΊΡΠΎΠ²"
, CASE
WHEN random() < 1::real/16 THEN NULL
ELSE (random() * 100)::integer -- 100 ΡΠ°Π·Π½ΡΡ Π²Π½Π΅ΡΠ½ΠΈΡ ΠΊΠ»ΡΡΠ΅ΠΉ
END fk_own
, (random() < 1::real/50) critical; -- 1:50, ΡΡΠΎ Π·Π°ΡΠ²ΠΊΠ° "ΠΊΡΠΈΡΠΈΡΠ½Π°Ρ"
CREATE INDEX ON tbl(pk);
CREATE INDEX ON tbl(fk_own, pk);
SELECT
*
FROM
tbl
WHERE
critical
ORDER BY
pk
LIMIT 20;
Ikusten duzunez, iragazketa erabat desagertu da planetik, eta eskaera bihurtu da 5 aldiz azkarrago.
#5: mahai eskasa
Sortzen denean
Zereginen prozesatzeko ilara propioa sortzeko hainbat saiakerak, mahai gainean dauden erregistroen eguneratze/ezabatze kopuru handi batek "hildako" erregistro kopuru handi bat eragiten duenean.
Egin eskuz aldizka HUTSEAN [BETEA] edo behar bezain maiz prestakuntza lortzea autohutsean bere parametroak finkatuz, besteak beste mahai zehatz baterako.
Badirudi pixka bat irakurri dugula, eta dena indexatu egin dela, eta ez dugu gehiegizko inor iragazi, baina hala ere nahi baino orrialde gehiago irakurtzen ditugu.
Begiratu arretaz erabilitako indizearen egitura eta kontsultan zehaztutako gako-eremuak - ziurrenik indizearen zati bat ez dago ezarrita. Ziurrenik antzeko indize bat sortu beharko duzu, baina aurrizki-eremurik gabe edo haien balioak errepikatzen ikasi.
Badirudi dena ondo dagoela, baita indizearen arabera ere, baina nolabait susmagarria da - irakurritako 20 erregistro bakoitzeko 4 datu kendu behar izan ditugu, 32 KB erregistro bakoitzeko - ez al da lodia? Eta indizearen izena tbl_fk_org_fk_cli_idx gogoeta eragitea.
Erregistro kopuru handi baten behin-behineko prozesatzea (ordenatzea edo bakartzea) ez da horretarako esleitutako memorian sartzen.
Nola identifikatu
-> *
&& temp written > 0
Gomendioak
Eragiketak erabiltzen duen memoria kopurua parametroaren zehaztutako balioa asko gainditzen ez badu lan_mem, merezi du zuzentzea. Berehala konfigurazioan sartu dezakezu guztiontzat, edo egin dezakezu SET [LOCAL] eskaera/transakzio zehatz baterako.
Adibidea:
SHOW work_mem;
-- "16MB"
SELECT
random()
FROM
generate_series(1, 1000000)
ORDER BY
1;
Ageriko arrazoiengatik, memoria bakarrik erabiltzen bada eta ez diskoa, orduan kontsulta askoz azkarrago exekutatuko da. Aldi berean, HDDko kargaren zati bat ere kentzen da.
Baina ulertu behar duzu ez duzula beti memoria asko eta asko esleitu ahal izango; besterik gabe, ez da denentzat nahikoa izango.
#9: garrantzirik gabeko estatistikak
Sortzen denean
Datu-basera asko isurtzen zuten aldi berean, baina ez zuten urruntzeko astirik izan ANALYZE.
Nola identifikatu
-> Seq Scan | Bitmap Heap Scan | Index [Only] Scan [Backward]
&& ratio >> 10
Eskaera lehiakide batek ezarritako blokeo baten itxaron bat egon zen, edo ez zegoen CPU/hipervisorearen hardware baliabide nahikorik.
Nola identifikatu
-> *
&& (shared hit / 8K) + (shared read / 1K) < time / 1000
-- RAM hit = 64MB/s, HDD read = 8MB/s
&& time > 100ms -- ΡΠΈΡΠ°Π»ΠΈ ΠΌΠ°Π»ΠΎ, Π½ΠΎ ΡΠ»ΠΈΡΠΊΠΎΠΌ Π΄ΠΎΠ»Π³ΠΎ
Gomendioak
Erabili kanpokoa jarraipen-sistema baliabideak blokeatzeko edo anormalaren kontsumoa egiteko zerbitzaria. Dagoeneko hitz egin dugu ehunka zerbitzarietarako prozesu hau antolatzeko dugun bertsioari buruz Hemen ΠΈ Hemen.