Sampeyan wis nggunakake luwih saka 6000 kaping, nanging siji fitur praktis sing bisa uga ora digatekake yaiku pitunjuk struktural, sing katon kaya iki:
Rungokake, lan panjaluk sampeyan bakal "dadi alus lan sutra". π
Nanging serius, akeh kahanan sing nggawe panjalukan alon lan keluwen sumber daya khas lan bisa dikenali dening struktur lan data rencana.
Ing kasus iki, saben pangembang individu ora kudu nggoleki pilihan optimasi dhewe, mung gumantung ing pengalaman - kita bisa ngomong apa sing kedadeyan ing kene, apa sing bisa dadi alesan, lan carane pendekatan solusi. Sing apa kita nindakake.
Ayo goleki kanthi luwih rinci babagan kasus kasebut - kepiye ditetepake lan rekomendasi apa sing ditindakake.
Kanggo luwih kacemplungaken dhewe ing topik, sampeyan bisa pisanan ngrungokake pamblokiran cocog saka laporanku ing PGConf.Russia 2020, lan banjur pindhah menyang analisis rinci saben conto:
#1: indeks "undersorting"
Nalika iku
Tampilake invoice paling anyar kanggo klien "LLC Kolokolchik".
Malah ing sampel primitif kuwi - 8.5 kaping luwih cepet lan 33 kaping kurang maca. Sing liyane "fakta" sampeyan duwe kanggo saben nilai, efek liyane ketok fk.
Aku nyathet yen indeks kasebut bakal digunakake minangka indeks "awalan" ora luwih elek tinimbang sadurunge kanggo pitakon liyane fk, ngendi urut miturut pk ora ana lan ora ana (sampeyan bisa maca liyane babagan iki ing artikelku babagan nemokake indeks sing ora efektif). Kalebu, bakal nyedhiyakake normal dhukungan kunci asing sing eksplisit ing lapangan iki.
#2: persimpangan indeks (BitmapAnd)
Nalika iku
Tampilake kabeh persetujuan kanggo klien "LLC Kolokolchik", rampung atas jenenge "NAO Buttercup".
Carane ngenali
-> BitmapAnd
-> Bitmap Index Scan
-> Bitmap Index Scan
Rekomendasi
nggawe indeks komposit dening kolom saka loro sing asli utawa nggedhekake salah siji sing wis ana karo kolom saka kaloro.
Conto:
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, Π±ΠΎΠ»ΡΡΠ΅ ΠΈ Π½Π΅ Π½Π°Π΄ΠΎ
Kita njupuk kauntungan saka kasunyatan manawa kabeh 20 cathetan sing dibutuhake langsung ditampa ing blok pertama, mula sing nomer loro, kanthi Pindai Heap Bitmap sing luwih "larang", malah ora dieksekusi - ing pungkasan. 22x luwih cepet, 44x luwih sithik maca!
Nggawe [liyane] khusus indeks kanthi kondisi WHERE utawa kalebu lapangan tambahan ing indeks.
Yen kondisi panyaring "statis" kanggo tujuan sampeyan - yaiku ora ateges expansion dhaptar nilai ing mangsa ngarep - luwih becik nggunakake indeks WHERE. Macem-macem status boolean/enum pas karo kategori iki.
Yen kahanan nyaring bisa njupuk macem-macem makna, banjur luwih apik kanggo nggedhekake indeks kanthi kolom kasebut - kaya ing kahanan BitmapAnd ndhuwur.
Conto:
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;
Nalika sampeyan bisa ndeleng, nyaring wis rampung ilang saka rencana, lan panjalukan wis dadi 5 kaping luwih cepet.
# 5: meja jarang
Nalika iku
Various nyoba kanggo nggawe antrian Processing tugas dhewe, nalika nomer akeh nganyari / pambusakan cathetan ing meja mimpin kanggo kahanan nomer akeh "mati" cathetan.
Nindakake kanthi manual kanthi rutin VACUUM [PENUH] utawa entuk latihan sing cukup kerep autovakum dening fine-tuning sawijining paramèter, kalebu kanggo tabel tartamtu.
Kayane kita maca sethithik, lan kabeh wis diindeks, lan kita ora nyaring sapa wae sing berlebihan - nanging isih maca luwih akeh kaca tinimbang sing dikarepake.
Deleng kanthi cetha ing struktur indeks sing digunakake lan kolom kunci sing ditemtokake ing pitakon - paling mungkin bagean saka indeks ora kasebut. Kemungkinan sampeyan kudu nggawe indeks sing padha, nanging tanpa kolom awalan utawa sinau kanggo ngulang nilai-nilai kasebut.
Kabeh katon apik, sanajan miturut indeks, nanging ana sing curiga - kanggo saben 20 cathetan sing diwaca, kita kudu nyuda 4 halaman data, 32KB saben rekaman - apa ora wani? Lan jeneng indeks tbl_fk_org_fk_cli_idx nggugah pikiran.
Processing siji-wektu (ngurutake utawa uniqueization) saka nomer akeh cathetan ora pas menyang memori diparengake kanggo iki.
Carane ngenali
-> *
&& temp written > 0
Rekomendasi
Yen jumlah memori digunakake dening operasi ora nemen ngluwihi Nilai kasebut parameter kerja_mem, iku worth mbenerake. Sampeyan bisa langsung ing config for everyone, utawa sampeyan bisa liwat SET [LOCAL] kanggo panjalukan / transaksi tartamtu.
Conto:
SHOW work_mem;
-- "16MB"
SELECT
random()
FROM
generate_series(1, 1000000)
ORDER BY
1;
Ana Enteni kanggo kunci dileksanakake dening request saingan, utawa ora cukup CPU / sumber hardware hypervisor.
Carane ngenali
-> *
&& (shared hit / 8K) + (shared read / 1K) < time / 1000
-- RAM hit = 64MB/s, HDD read = 8MB/s
&& time > 100ms -- ΡΠΈΡΠ°Π»ΠΈ ΠΌΠ°Π»ΠΎ, Π½ΠΎ ΡΠ»ΠΈΡΠΊΠΎΠΌ Π΄ΠΎΠ»Π³ΠΎ
Rekomendasi
Gunakake njaba sistem monitoring server kanggo mblokir utawa konsumsi sumber ora normal. Kita wis ngomong babagan versi ngatur proses iki kanggo atusan server kene ΠΈ kene.