Шумо онро аллакай зиёда аз 6000 маротиба истифода кардаед, аммо як хусусияти муфид, ки шояд нодида гирифта шавад нишондодҳои сохторӣ, ки чизе монанди ин аст:
Ба онҳо гӯш диҳед, ва дархостҳои шумо "ҳамвор ва абрешим хоҳанд шуд". 🙂
Аммо ба таври ҷиддӣ, бисёр ҳолатҳо, ки дархостро суст ва ба захираҳо гурусна мекунанд хосанд ва аз руи структура ва маълумотхои план эътироф карда мешаванд.
Индекс истифода мешавад бо майдонҳои ҷудокунӣ васеъ кунед.
Мисол:
CREATE TABLE tbl AS
SELECT
generate_series(1, 100000) pk -- 100K "фактов"
, (random() * 1000)::integer fk_cli; -- 1K разных внешних ключей
CREATE INDEX ON tbl(fk_cli); -- индекс для foreign key
SELECT
*
FROM
tbl
WHERE
fk_cli = 1 -- отбор по конкретной связи
ORDER BY
pk DESC -- хотим всего одну "последнюю" запись
LIMIT 1;
-> BitmapAnd
-> Bitmap Index Scan
-> Bitmap Index Scan
тавсияњои
Эҷод кунед индекси таркиби аз рӯи майдонҳо аз ҳарду майдонҳои аслӣ ё яке аз майдонҳои мавҷударо бо майдонҳои дуюм васеъ кунед.
Мисол:
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); -- отбор по конкретной паре
-> BitmapOr
-> Bitmap Index Scan
-> Bitmap Index Scan
тавсияњои
Барои истифода ИТТИФОКИ [ХАМА] барои якҷоя кардани зерпурсишҳо барои ҳар яке аз OR-блокҳои шартҳо.
Мисол:
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, больше и не надо
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;
Чунин ба назар мерасад, ки мо каме хондем ва ҳама чиз индексатсия карда шуд ва мо ҳеҷ касро аз ҳад зиёд филтр накардем - аммо ба ҳар ҳол мо саҳифаҳои зиёдеро аз он ки мехостем, мехонем.
Чӣ тавр муайян кардан
-> Index [Only] Scan [Backward]
&& loops × (rows + RRbF) < (shared hit + shared read) × 8
-- прочитано больше 1KB на каждую запись
&& shared hit + shared read > 64
тавсияњои
Ба сохтори индекси истифодашуда ва майдонҳои калидии дар дархост нишондодашуда бодиққат назар кунед - эҳтимоли зиёд як кисми индекс мукаррар карда нашудааст. Эҳтимол дорад, ки шумо бояд як шохиси шабеҳ эҷод кунед, аммо бидуни майдонҳои префикс ё арзишҳои худро такрор карданро ёд гиред.
Мисол:
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, fk_cli); -- все почти как в #2
-- только вот отдельный индекс по fk_cli мы уже посчитали лишним и удалили
SELECT
*
FROM
tbl
WHERE
fk_cli = 999 -- а fk_org не задано, хотя стоит в индексе раньше
LIMIT 20;
Ба назар чунин мерасад, ки ҳама чиз хуб аст, ҳатто аз рӯи индекс, аммо он то андозае шубҳанок аст - барои ҳар як аз 20 сабти хондашуда, мо бояд 4 саҳифаи маълумот, 32 КБ барои як сабтро хориҷ кунем - оё ин ғафс нест? Ва номи индекс tbl_fk_org_fk_cli_idx ба андеша водоркунанда.
Бо сабабҳои маълум, агар танҳо хотира истифода шавад, на диск, он гоҳ дархост хеле тезтар иҷро карда мешавад. Дар айни замон, як қисми сарборӣ аз HDD низ хориҷ карда мешавад.
Аммо шумо бояд фаҳмед, ки шумо на ҳама вақт хотираи зиёдеро ҷудо карда наметавонед - он барои ҳама кофӣ нахоҳад буд.
№9: омори номарбуте
Вақте ки ба миён меояд
Онҳо якбора ба базаи маълумот бисёр рехтанд, аммо барои дур кардани он вақт надоштанд ANALYZE.
Чӣ тавр муайян кардан
-> Seq Scan | Bitmap Heap Scan | Index [Only] Scan [Backward]
&& ratio >> 10