Efa in-6000 XNUMX mahery no nampiasanao azy, fa ny endri-javatra iray azo ampiasaina izay mety tsy voamarika dia famantarana ara-drafitra, izay toa izao:
Henoy izy ireo, dia βho malama sy landyβ ny fangatahanao. π
Fa ny tena zava-dehibe, toe-javatra maro izay mahatonga ny fangatahana miadana sy mandany loharanon-karena dia mahazatra ary azo fantarina amin'ny rafitra sy ny angon-drakitra momba ny drafitra.
Amin'ity tranga ity, ny mpamorona tsirairay dia tsy mila mitady safidy optimization ho azy manokana, miantehitra fotsiny amin'ny traikefany - azontsika lazaina aminy ny zava-mitranga eto, inona no mety ho antony, ary ny fomba hanatonana vahaolana. Izany no nataonay.
Andeha hojerentsika akaiky ireo tranga ireo - ny fomba hamaritana azy ireo sy ny tolo-kevitra entiny.
Mba hiroboka tsara kokoa amin'ny lohahevitra dia azonao atao aloha ny mihaino ny sakana mifandraika amin'izany ny tatitro tao amin'ny PGConf.Russia 2020, ary avy eo dia miroso amin'ny famakafakana antsipirihan'ny ohatra tsirairay:
Hitanao avy hatrany fa mihoatra ny 100 ny firaketana no nesorina tao amin'ny index, izay nalahatra daholo avy eo, ary avy eo dia ny iray ihany no tavela.
Ahitsio
DROP INDEX tbl_fk_cli_idx;
CREATE INDEX ON tbl(fk_cli, pk DESC); -- Π΄ΠΎΠ±Π°Π²ΠΈΠ»ΠΈ ΠΊΠ»ΡΡ ΡΠΎΡΡΠΈΡΠΎΠ²ΠΊΠΈ
Na dia amin'ny santionany voalohany toy izany aza - 8.5 heny haingana kokoa ary in-33 heny ny famakiana. Arakaraka ny "zava-misy" anananao isaky ny sandany no miharihary kokoa ny vokany fk.
Marihiko fa ny fanondroana toy izany dia hiasa toy ny fanondroana "prefix" tsy ratsy noho ny teo aloha ho an'ny fanontaniana hafa miaraka fk, aiza no alamina pk tsy nisy ary tsy nisy (afaka mamaky bebe kokoa momba an'io ianao ao amin'ny lahatsoratro momba ny fitadiavana indeksa tsy mahomby). Anisan'izany, dia hanome ara-dalΓ na fanohanana fanalahidy vahiny mazava amin'ity sehatra ity.
#2: fihaonan'ny fanondro (BitmapAnd)
Rehefa mipoitra
Asehoy ny fifanarahana rehetra ho an'ny mpanjifa "LLC Kolokolchik", namarana tamin'ny anaran'ny "NAO Buttercup".
Ahoana no hamantarana
-> BitmapAnd
-> Bitmap Index Scan
-> Bitmap Index Scan
tolo-kevitra
mamorona fanondroana mitambatra amin'ny saha avy amin'ny tany am-boalohany na manitatra ny iray amin'ireo efa misy miaraka amin'ny saha avy amin'ny faharoa.
ohatra:
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); -- ΠΎΡΠ±ΠΎΡ ΠΏΠΎ ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½ΠΎΠΉ ΠΏΠ°ΡΠ΅
Ny karama eto dia kely kokoa, satria ny Bitmap Heap Scan dia mahomby amin'ny tenany manokana. Saingy na izany aza 7 heny haingana kokoa ary in-2.5 heny ny famakiana.
#3: Manambatra tondro (BitmapOr)
Rehefa mipoitra
Asehoy ireo 20 tranainy indrindra βisikaβ na fangatahana tsy voatendry ho an'ny fanodinana, ka ny anao no laharam-pahamehana.
Ahoana no hamantarana
-> BitmapOr
-> Bitmap Index Scan
-> Bitmap Index Scan
tolo-kevitra
Ampiasao UNION [REHETRA] mba hanambatra ny subqueries ho an'ny tsirairay amin'ny OR-bloka ny fepetra.
ohatra:
CREATE TABLE tbl AS
SELECT
generate_series(1, 100000) pk -- 100K "ΡΠ°ΠΊΡΠΎΠ²"
, CASE
WHEN random() < 1::real/16 THEN NULL -- Ρ Π²Π΅ΡΠΎΡΡΠ½ΠΎΡΡΡΡ 1:16 Π·Π°ΠΏΠΈΡΡ "Π½ΠΈΡΡΡ"
ELSE (random() * 100)::integer -- 100 ΡΠ°Π·Π½ΡΡ Π²Π½Π΅ΡΠ½ΠΈΡ ΠΊΠ»ΡΡΠ΅ΠΉ
END fk_own;
CREATE INDEX ON tbl(fk_own, pk); -- ΠΈΠ½Π΄Π΅ΠΊΡ Ρ "Π²ΡΠΎΠ΄Π΅ ΠΊΠ°ΠΊ ΠΏΠΎΠ΄Ρ ΠΎΠ΄ΡΡΠ΅ΠΉ" ΡΠΎΡΡΠΈΡΠΎΠ²ΠΊΠΎΠΉ
SELECT
*
FROM
tbl
WHERE
fk_own = 1 OR -- ΡΠ²ΠΎΠΈ
fk_own IS NULL -- ... ΠΈΠ»ΠΈ "Π½ΠΈΡΡΠΈ"
ORDER BY
pk
, (fk_own = 1) DESC -- ΡΠ½Π°ΡΠ°Π»Π° "ΡΠ²ΠΎΠΈ"
LIMIT 20;
(
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, Π±ΠΎΠ»ΡΡΠ΅ ΠΈ Π½Π΅ Π½Π°Π΄ΠΎ
Amin'ny maha-fitsipika azy dia mipoitra izany rehefa te "hampiditra sivana hafa" amin'ny fangatahana efa misy ianao.
βAry tsy manana iray ianao, fa miaraka amin'ny bokotra renin'ny perla? " sarimihetsika "The Diamond Arm"
Ohatra, ny fanovana ny asa etsy ambony, dia asehoy ny fangatahana "kritika" 20 voalohany indrindra ho an'ny fanodinana, na inona na inona tanjon'izy ireo.
Mamorona [more] manokana fanondro misy fepetra WHERE na ampidiro saha fanampiny ao amin'ny fanondroana.
Raha "static" ho an'ny tanjonao ny fepetra sivana - izany hoe tsy midika fanitarana lisitry ny soatoavina amin'ny ho avy - tsara kokoa ny mampiasa index WHERE. Ny sata boolean/enum isan-karazany dia mifanentana tsara amin'ity sokajy ity.
Raha ny fepetra sivana afaka mitondra dikany samihafa, dia tsara kokoa ny manitatra ny index miaraka amin'ireo saha ireo - toy ny amin'ny toe-javatra misy an'i BitmapAnd etsy ambony.
ohatra:
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;
Jereo akaiky ny firafitry ny tondro ampiasaina sy ny saha fototra voatondro ao amin'ny fangatahana - azo inoana fa tsy voafaritra ny ampahany amin'ny fanondroana. Azo inoana fa tsy maintsy mamorona tondro mitovy amin'izany ianao, saingy tsy misy saha misy prefix na mianatra mamerina ny soatoaviny.
Toa tsara daholo ny zava-drehetra, na dia araka ny fanondroana aza, saingy mampiahiahy izany - ho an'ny rakitsoratra 20 tsirairay novakiana, dia tsy maintsy nesorinay ny angon-drakitra pejy 4, 32KB isaky ny rakitra - tsy sahy ve izany? Ary ny anarana fanondro tbl_fk_org_fk_cli_idx mampieritreritra.
Ny fanodinana indray mandeha (fanasokajiana na fanavahana) ny rakitra marobe dia tsy mifanaraka amin'ny fitadidiana natokana ho an'izany.
Ahoana no hamantarana
-> *
&& temp written > 0
tolo-kevitra
Raha ny habetsaky ny fahatsiarovana ampiasain'ny fandidiana dia tsy mihoatra ny sanda voafaritra amin'ny parameter work_mem, mendrika ny hanitsiana izany. Azonao atao avy hatrany ao amin'ny config ho an'ny rehetra, na azonao atao SET [LOCAL] ho an'ny fangatahana / fifampiraharahana manokana.
ohatra:
SHOW work_mem;
-- "16MB"
SELECT
random()
FROM
generate_series(1, 1000000)
ORDER BY
1;
Noho ny antony mazava, raha fitadidiana ihany no ampiasaina fa tsy kapila, dia ho haingana kokoa ny fangatahana. Mandritra izany fotoana izany, esorina ihany koa ny ampahany amin'ny entana avy amin'ny HDD.
Saingy mila takatrao fa tsy ho afaka hanokana fahatsiarovana be dia be ianao - tsy ho ampy ho an'ny rehetra.