เชฌเซ€เชฎเชพเชฐ SQL เชชเซเชฐเชถเซเชจเซ‹ เชฎเชพเชŸเซ‡ เชตเชพเชจเช—เซ€เช“

เชฎเชนเชฟเชจเชพเช“ เชชเซ‡เชนเซเชฒเชพ เช…เชฎเซ‡ เชœเชพเชนเซ‡เชฐเชพเชค เช•เชฐเซ€ explain.tensor.ru - เชœเชพเชนเซ‡เชฐ เช•เซเชตเซ‡เชฐเซ€ เชชเซเชฒเชพเชจเชจเซ‡ เชชเชพเชฐเซเชธเชฟเช‚เช— เช…เชจเซ‡ เชตเชฟเชเซเชฏเซเช…เชฒเชพเชˆเช เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡เชจเซ€ เชธเซ‡เชตเชพ PostgreSQL เชฎเชพเชŸเซ‡.

เชคเชฎเซ‡ เชชเชนเซ‡เชฒเชพเชฅเซ€ เชœ เชคเซ‡เชจเซ‹ 6000 เชฅเซ€ เชตเชงเซ เชตเช–เชค เช‰เชชเชฏเซ‹เช— เช•เชฐเซเชฏเซ‹ เช›เซ‡, เชชเชฐเช‚เชคเซ เชเช• เชธเชฐเชณ เชธเซเชตเชฟเชงเชพ เชœเซ‡เชจเซเช‚ เชงเซเชฏเชพเชจ เช—เชฏเซเช‚ เชจเชฅเซ€ เชคเซ‡ เช›เซ‡ เชฎเชพเชณเช–เชพเช•เซ€เชฏ เชธเช‚เช•เซ‡เชคเซ‹, เชœเซ‡ เช•เช‚เชˆเช• เช†เชจเชพ เชœเซ‡เชตเซเช‚ เชฆเซ‡เช–เชพเชฏ เช›เซ‡:

เชฌเซ€เชฎเชพเชฐ SQL เชชเซเชฐเชถเซเชจเซ‹ เชฎเชพเชŸเซ‡ เชตเชพเชจเช—เซ€เช“

เชคเซ‡เชฎเชจเซ‡ เชธเชพเช‚เชญเชณเซ‹, เช…เชจเซ‡ เชคเชฎเชพเชฐเซ€ เชตเชฟเชจเช‚เชคเซ€เช“ "เชธเชฐเชณ เช…เชจเซ‡ เชฐเซ‡เชถเชฎเซ€ เชฌเชจเซ€ เชœเชถเซ‡." ๐Ÿ™‚

เชชเชฐเช‚เชคเซ เช—เช‚เชญเซ€เชฐเชคเชพเชชเซ‚เชฐเซเชตเช•, เช˜เชฃเซ€ เชชเชฐเชฟเชธเซเชฅเชฟเชคเชฟเช“ เชœเซ‡ เชตเชฟเชจเช‚เชคเซ€เชจเซ‡ เชงเซ€เชฎเซ€ เช…เชจเซ‡ เชธเช‚เชธเชพเชงเชจ-เชญเซ‚เช–เซเชฏเชพ เชฌเชจเชพเชตเซ‡ เช›เซ‡ เชฒเชพเช•เซเชทเชฃเชฟเช• เช›เซ‡ เช…เชจเซ‡ เชฏเซ‹เชœเชจเชพเชจเชพ เชฎเชพเชณเช–เชพ เช…เชจเซ‡ เชกเซ‡เชŸเชพ เชฆเซเชตเชพเชฐเชพ เช“เชณเช–เซ€ เชถเช•เชพเชฏ เช›เซ‡.

เช† เช•เชฟเชธเซเชธเชพเชฎเชพเช‚, เชฆเชฐเซ‡เช• เชตเซเชฏเช•เซเชคเชฟเช—เชค เชตเชฟเช•เชพเชธเช•เชฐเซเชคเชพเช เชซเช•เซเชค เชคเซ‡เชจเชพ เช…เชจเซเชญเชต เชชเชฐ เช†เชงเชพเชฐ เชฐเชพเช–เซ€เชจเซ‡, เชคเซ‡เชจเชพ เชชเซ‹เชคเชพเชจเชพ เชชเชฐ เช‘เชชเซเชŸเชฟเชฎเชพเช‡เชเซ‡เชถเชจ เชตเชฟเช•เชฒเซเชช เชถเซ‹เชงเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เชจเชฅเซ€ - เช…เชฎเซ‡ เชคเซ‡เชจเซ‡ เช•เชนเซ€ เชถเช•เซ€เช เช•เซ‡ เช…เชนเซ€เช‚ เชถเซเช‚ เชฅเชˆ เชฐเชนเซเชฏเซเช‚ เช›เซ‡, เช•เชพเชฐเชฃ เชถเซเช‚ เชนเซ‹เชˆ เชถเช•เซ‡ เช›เซ‡, เช…เชจเซ‡ เช‰เช•เซ‡เชฒเชจเซ‹ เชธเช‚เชชเชฐเซเช• เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เช•เชฐเชตเซ‹. เชคเซ‡ เช…เชฎเซ‡ เช•เชฐเซเชฏเซเช‚ เช›เซ‡.

เชฌเซ€เชฎเชพเชฐ SQL เชชเซเชฐเชถเซเชจเซ‹ เชฎเชพเชŸเซ‡ เชตเชพเชจเช—เซ€เช“

เชšเชพเชฒเซ‹ เช† เช•เซ‡เชธเซ‹ เชชเชฐ เชจเชœเซ€เช•เชฅเซ€ เชจเชœเชฐ เช•เชฐเซ€เช - เชคเซ‡เช“ เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เชตเซเชฏเชพเช–เซเชฏเชพเชฏเชฟเชค เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡ เช…เชจเซ‡ เชคเซ‡เช“ เช•เชˆ เชญเชฒเชพเชฎเชฃเซ‹ เชคเชฐเชซ เชฆเซ‹เชฐเซ€ เชœเชพเชฏ เช›เซ‡.

เชตเชฟเชทเชฏเชฎเชพเช‚ เชคเชฎเชพเชฐเซ€ เชœเชพเชคเชจเซ‡ เชตเชงเซ เชธเชพเชฐเซ€ เชฐเซ€เชคเซ‡ เชจเชฟเชฎเชœเซเชœเชจ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡, เชคเชฎเซ‡ เชชเชนเซ‡เชฒเชพ เชคเซ‡เชจเชพ เช…เชจเซเชฐเซ‚เชช เชฌเซเชฒเซ‹เช•เชจเซ‡ เชธเชพเช‚เชญเชณเซ€ เชถเช•เซ‹ เช›เซ‹ PGConf.Russia 2020 เชชเชฐ เชฎเชพเชฐเซ‹ เช…เชนเซ‡เชตเชพเชฒ, เช…เชจเซ‡ เชชเช›เซ€ เชœ เชฆเชฐเซ‡เช• เช‰เชฆเชพเชนเชฐเชฃเชจเชพ เชตเชฟเช—เชคเชตเชพเชฐ เชตเชฟเชถเซเชฒเซ‡เชทเชฃ เชคเชฐเชซ เช†เช—เชณ เชตเชงเซ‹:

#1: เช…เชจเซเช•เซเชฐเชฎเชฃเชฟเช•เชพ "เช…เช‚เชกเชฐเชธเซ‹เชฐเซเชŸเชฟเช‚เช—"

เชœเซเชฏเชพเชฐเซ‡ เช‰เชฆเชญเชตเซ‡ เช›เซ‡

เช•เซเชฒเชพเชฏเช‚เชŸ "LLC Kolokolchik" เชฎเชพเชŸเซ‡ เชจเชตเซ€เชจเชคเชฎ เช‡เชจเซเชตเซ‰เช‡เชธ เชฌเชคเชพเชตเซ‹.

เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เช“เชณเช–เชตเซเช‚

-> Limit
   -> Sort
      -> Index [Only] Scan [Backward] | Bitmap Heap Scan

เชญเชฒเชพเชฎเชฃเซ‹

เช…เชจเซเช•เซเชฐเชฎเชฃเชฟเช•เชพ เชตเชชเชฐเชพเชฏ เช›เซ‡ เชธเซ‰เชฐเซเชŸ เช•เซเชทเซ‡เชคเซเชฐเซ‹ เชธเชพเชฅเซ‡ เชตเชฟเชธเซเชคเซƒเชค เช•เชฐเซ‹.

เช‰เชฆเชพเชนเชฐเชฃ:

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;

เชฌเซ€เชฎเชพเชฐ SQL เชชเซเชฐเชถเซเชจเซ‹ เชฎเชพเชŸเซ‡ เชตเชพเชจเช—เซ€เช“
[explan.tensor.ru เชชเชฐ เชœเซเช“]

เชคเชฎเซ‡ เชคเชฐเชค เชœ เชจเซ‹เช‚เชง เช•เชฐเซ€ เชถเช•เซ‹ เช›เซ‹ เช•เซ‡ เช…เชจเซเช•เซเชฐเชฎเชฃเชฟเช•เชพเชฎเชพเช‚เชฅเซ€ 100 เชฅเซ€ เชตเชงเซ เชฐเซ‡เช•เซ‹เชฐเซเชกเซเชธ เชฌเชพเชฆ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซเชฏเชพ เชนเชคเชพ, เชœเซ‡ เชชเช›เซ€ เชฌเชงเชพ เชธเซ‰เชฐเซเชŸ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซเชฏเชพ เชนเชคเชพ, เช…เชจเซ‡ เชชเช›เซ€ เชฎเชพเชคเซเชฐ เชเช• เชœ เชฌเชพเช•เซ€ เชนเชคเซ‹.

เชธเซเชงเชพเชฐเซ€ เชฐเชนเซเชฏเซเช‚ เช›เซ‡:

DROP INDEX tbl_fk_cli_idx;
CREATE INDEX ON tbl(fk_cli, pk DESC); -- ะดะพะฑะฐะฒะธะปะธ ะบะปัŽั‡ ัะพั€ั‚ะธั€ะพะฒะบะธ

เชฌเซ€เชฎเชพเชฐ SQL เชชเซเชฐเชถเซเชจเซ‹ เชฎเชพเชŸเซ‡ เชตเชพเชจเช—เซ€เช“
[explan.tensor.ru เชชเชฐ เชœเซเช“]

เช†เชตเชพ เช†เชฆเชฟเชฎ เชจเชฎเซ‚เชจเชพ เชชเชฐ เชชเชฃ - 8.5 เช—เชฃเซ€ เชเชกเชชเซ€ เช…เชจเซ‡ 33 เช—เชฃเซ€ เช“เช›เซ€ เชตเชพเช‚เชšเชจ. เชฆเชฐเซ‡เช• เชฎเซ‚เชฒเซเชฏ เชฎเชพเชŸเซ‡ เชคเชฎเชพเชฐเซ€ เชชเชพเชธเซ‡ เชœเซ‡เชŸเชฒเซ€ เชตเชงเซ "เชคเชฅเซเชฏเซ‹" เชนเชถเซ‡, เชคเซ‡เชŸเชฒเซ€ เชตเชงเซ เชธเซเชชเชทเซเชŸ เช…เชธเชฐ fk.

เชนเซเช‚ เชจเซ‹เช‚เชงเซเช‚ เช›เซเช‚ เช•เซ‡ เช†เชตเซ€ เช…เชจเซเช•เซเชฐเชฎเชฃเชฟเช•เชพ "เช‰เชชเชธเชฐเซเช—" เช…เชจเซเช•เซเชฐเชฎเชฃเชฟเช•เชพ เชคเชฐเซ€เช•เซ‡ เช•เชพเชฎ เช•เชฐเชถเซ‡ เชœเซ‡ เช…เชจเซเชฏ เชชเซเชฐเชถเซเชจเซ‹ เชฎเชพเชŸเซ‡ เชชเชนเซ‡เชฒเชพเช‚ เช•เชฐเชคเชพเช‚ เชตเชงเซ เช–เชฐเชพเชฌ เชจเชฅเซ€. fk, เชœเซเชฏเชพเช‚ เชฆเซเชตเชพเชฐเชพ เชธเซ‰เชฐเซเชŸ เช•เชฐเซ‹ pk เชคเซเชฏเชพเช‚ เชจ เชนเชคเซเช‚ เช…เชจเซ‡ เชคเซเชฏเชพเช‚ เชจเชฅเซ€ (เชคเชฎเซ‡ เช† เชตเชฟเชถเซ‡ เชตเชงเซ เชตเชพเช‚เชšเซ€ เชถเช•เซ‹ เช›เซ‹ เชฌเชฟเชจเช…เชธเชฐเช•เชพเชฐเช• เชธเซ‚เชšเช•เชพเช‚เช•เซ‹ เชถเซ‹เชงเชตเชพ เชตเชฟเชถเซ‡เชจเชพ เชฎเชพเชฐเชพ เชฒเซ‡เช–เชฎเชพเช‚). เชธเชนเชฟเชค, เชคเซ‡ เชธเชพเชฎเชพเชจเซเชฏ เชชเซเชฐเชฆเชพเชจ เช•เชฐเชถเซ‡ เชธเซเชชเชทเซเชŸ เชตเชฟเชฆเซ‡เชถเซ€ เช•เซ€ เช†เชงเชพเชฐ เช† เช•เซเชทเซ‡เชคเซเชฐ เชชเชฐ.

#2: เช…เชจเซเช•เซเชฐเชฎเชฃเชฟเช•เชพ เช†เช‚เชคเชฐเช›เซ‡เชฆ (เชฌเซ€เชŸเชฎเซ‡เชชเช…เชจเซ‡)

เชœเซเชฏเชพเชฐเซ‡ เช‰เชฆเชญเชตเซ‡ เช›เซ‡

โ€œNAO เชฌเชŸเชฐเช•เชชโ€ เชตเชคเซ€ เชธเชฎเชพเชชเซเชค เชฅเชฏเซ‡เชฒ เช•เซเชฒเชพเชฏเชจเซเชŸ โ€œLLC Kolokolchikโ€ เชฎเชพเชŸเซ‡เชจเชพ เชคเชฎเชพเชฎ เช•เชฐเชพเชฐเซ‹ เชฌเชคเชพเชตเซ‹.

เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เช“เชณเช–เชตเซเช‚

-> 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); -- ะพั‚ะฑะพั€ ะฟะพ ะบะพะฝะบั€ะตั‚ะฝะพะน ะฟะฐั€ะต

เชฌเซ€เชฎเชพเชฐ SQL เชชเซเชฐเชถเซเชจเซ‹ เชฎเชพเชŸเซ‡ เชตเชพเชจเช—เซ€เช“
[explan.tensor.ru เชชเชฐ เชœเซเช“]

เชธเซเชงเชพเชฐเซ€ เชฐเชนเซเชฏเซเช‚ เช›เซ‡:

DROP INDEX tbl_fk_org_idx;
CREATE INDEX ON tbl(fk_org, fk_cli);

เชฌเซ€เชฎเชพเชฐ SQL เชชเซเชฐเชถเซเชจเซ‹ เชฎเชพเชŸเซ‡ เชตเชพเชจเช—เซ€เช“
[explan.tensor.ru เชชเชฐ เชœเซเช“]

เช…เชนเซ€เช‚ เชšเซ‚เช•เชตเชฃเซ€ เช“เช›เซ€ เช›เซ‡, เช•เชพเชฐเชฃ เช•เซ‡ เชฌเซ€เชŸเชฎเซ‡เชช เชนเซ€เชช เชธเซเช•เซ‡เชจ เชคเซ‡เชจเชพ เชชเซ‹เชคเชพเชจเชพ เชชเชฐ เช–เซ‚เชฌ เช…เชธเชฐเช•เชพเชฐเช• เช›เซ‡. เชชเชฐเช‚เชคเซ เช•เซ‹เชˆเชชเชฃ เชฐเซ€เชคเซ‡ 7 เช—เชฃเซ€ เชเชกเชชเซ€ เช…เชจเซ‡ 2.5 เช—เชฃเซ€ เช“เช›เซ€ เชตเชพเช‚เชšเชจ.

#3: เช…เชจเซเช•เซเชฐเชฎเชฃเชฟเช•เชพเช“เชจเซ‡ เชฎเชฐเซเชœ เช•เชฐเซ‹ (เชฌเซ€เชŸเชฎเซ‡เชชเช“เชฐ)

เชœเซเชฏเชพเชฐเซ‡ เช‰เชฆเชญเชตเซ‡ เช›เซ‡

เชชเซเชฐเชฅเชฎ 20 เชธเซŒเชฅเซ€ เชœเซ‚เชจเซ€ โ€œเช…เชฎเชจเซ‡โ€ เช…เชฅเชตเชพ เชชเซเชฐเช•เซเชฐเชฟเชฏเชพ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡ เชธเซ‹เช‚เชชเซ‡เชฒ เชจ เช•เชฐเซ‡เชฒเซ€ เชตเชฟเชจเช‚เชคเซ€เช“, เชคเชฎเชพเชฐเซ€ เชชเซเชฐเชพเชฅเชฎเชฟเช•เชคเชพ เชธเชพเชฅเซ‡ เชฌเชคเชพเชตเซ‹.

เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เช“เชณเช–เชตเซเช‚

-> 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;

เชฌเซ€เชฎเชพเชฐ SQL เชชเซเชฐเชถเซเชจเซ‹ เชฎเชพเชŸเซ‡ เชตเชพเชจเช—เซ€เช“
[explan.tensor.ru เชชเชฐ เชœเซเช“]

เชธเซเชงเชพเชฐเซ€ เชฐเชนเซเชฏเซเช‚ เช›เซ‡:

(
  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, ะฑะพะปัŒัˆะต ะธ ะฝะต ะฝะฐะดะพ

เชฌเซ€เชฎเชพเชฐ SQL เชชเซเชฐเชถเซเชจเซ‹ เชฎเชพเชŸเซ‡ เชตเชพเชจเช—เซ€เช“
[explan.tensor.ru เชชเชฐ เชœเซเช“]

เช…เชฎเซ‡ เช เชนเช•เซ€เช•เชคเชจเซ‹ เชฒเชพเชญ เชฒเซ€เชงเซ‹ เชนเชคเซ‹ เช•เซ‡ เชชเซเชฐเชฅเชฎ เชฌเซเชฒเซ‹เช•เชฎเชพเช‚ เชคเชฎเชพเชฎ 20 เชœเชฐเซ‚เชฐเซ€ เชฐเซ‡เช•เซ‹เชฐเซเชกเซเชธ เชคเชฐเชค เชœ เชชเซเชฐเชพเชชเซเชค เชฅเชˆ เช—เชฏเชพ เชนเชคเชพ, เชคเซ‡เชฅเซ€ เชตเชงเซ "เช–เชฐเซเชšเชพเชณ" เชฌเซ€เชŸเชฎเซ‡เชช เชนเซ€เชช เชธเซเช•เซ‡เชจ เชธเชพเชฅเซ‡เชจเซ‹ เชฌเซ€เชœเซ‹ เชเช• เชชเชฃ เช…เชฎเชฒเชฎเชพเช‚ เช†เชตเซเชฏเซ‹ เชจ เชนเชคเซ‹ - เช…เช‚เชคเซ‡ 22x เชเชกเชชเซ€, 44x เช“เช›เชพ เชตเชพเช‚เชšเชจ!

เช† เช“เชชเซเชŸเชฟเชฎเชพเช‡เชเซ‡เชถเชจ เชชเชฆเซเชงเชคเชฟ เชตเชฟเชถเซ‡ เชตเชงเซ เชตเชฟเช—เชคเชตเชพเชฐ เชตเชพเชฐเซเชคเชพ เชšเซ‹เช•เซเช•เชธ เช‰เชฆเชพเชนเชฐเชฃเซ‹เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ เชฒเซ‡เช–เซ‹เชฎเชพเช‚ เชตเชพเช‚เชšเซ€ เชถเช•เชพเชฏ เช›เซ‡ PostgreSQL เชเชจเซเชŸเชฟเชชเซ‡เชŸเชฐเซเชจ: เชนเชพเชจเชฟเช•เชพเชฐเช• เชœเซ‹เชกเชพเช“ เช…เชจเซ‡ ORs ะธ เชชเซ‹เชธเซเชŸเช—เซเชฐเซ‡เชเชธเช•เซเชฏเซเชเชฒ เชเชจเซเชŸเชฟเชชเซ‡เชŸเชฐเซเชจ: เชจเชพเชฎ เชฆเซเชตเชพเชฐเชพ เชถเซ‹เชงเชจเชพ เชชเซเชจเชฐเชพเชตเชฐเซเชคเชฟเชค เชถเซเชฆเซเชงเชฟเช•เชฐเชฃเชจเซ€ เชตเชพเชฐเซเชคเชพ, เช…เชฅเชตเชพ "เช†เช—เชณ เช…เชจเซ‡ เช†เช—เชณ เช‘เชชเซเชŸเชฟเชฎเชพเช‡เช เช•เชฐเชตเซเช‚".

เชธเชพเชฎเชพเชจเซเชฏเช•เซƒเชค เชธเช‚เชธเซเช•เชฐเชฃ เช…เชจเซ‡เช• เช•เซ€เชจเชพ เช†เชงเชพเชฐเซ‡ เชชเชธเช‚เชฆเช—เซ€เชจเซ‹ เช†เชฆเซ‡เชถ เช†เชชเซเชฏเซ‹ (เช…เชจเซ‡ เชฎเชพเชคเซเชฐ const/NULL เชœเซ‹เชกเซ€ เชœ เชจเชนเซ€เช‚) เชฒเซ‡เช–เชฎเชพเช‚ เชšเชฐเซเชšเชพ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ€ เช›เซ‡ SQL HowTo: เช•เซเชตเซ‡เชฐเซ€ เช…เชฅเชตเชพ "เชชเซเชฐเชพเชฅเชฎเชฟเช• เชฅเซเชฐเซ€-เชตเซ‡"เชฎเชพเช‚ เชธเซ€เชงเชพ เชœ เชœเซเชฏเชพเชฐเซ‡-เชฒเซ‚เชช เชฒเช–เซ‹.

#4: เช†เชชเชฃเซ‡ เช˜เชฃเซ€ เชฌเชงเซ€ เชฌเชฟเชจเชœเชฐเซ‚เชฐเซ€ เชตเชธเซเชคเซเช“ เชตเชพเช‚เชšเซ€เช เช›เซ€เช

เชœเซเชฏเชพเชฐเซ‡ เช‰เชฆเชญเชตเซ‡ เช›เซ‡

เชเช• เชจเชฟเชฏเชฎ เชคเชฐเซ€เช•เซ‡, เชœเซเชฏเชพเชฐเซ‡ เชคเชฎเซ‡ เชชเชนเซ‡เชฒเชพเชฅเซ€ เช…เชธเซเชคเชฟเชคเซเชตเชฎเชพเช‚ เชฐเชนเซ‡เชฒเซ€ เชตเชฟเชจเช‚เชคเซ€ เชธเชพเชฅเซ‡ "เชฌเซ€เชœเชพ เชซเชฟเชฒเซเชŸเชฐเชจเซ‡ เชœเซ‹เชกเชตเชพ" เชฎเชพเช‚เช—เชคเชพ เชนเซ‹ เชคเซเชฏเชพเชฐเซ‡ เชคเซ‡ เช‰เชฆเซเชญเชตเซ‡ เช›เซ‡.

"เช…เชจเซ‡ เชคเชฎเชพเชฐเซ€ เชชเชพเชธเซ‡ เชคเซ‡ เชœ เชจเชฅเซ€, เชชเชฐเช‚เชคเซ เชฎเชงเชฐ-เช“เชซ-เชชเชฐเซเชฒ เชฌเชŸเชจเซ‹ เชธเชพเชฅเซ‡? เชซเชฟเชฒเซเชฎ "เชง เชกเชพเชฏเชฎเช‚เชก เช†เชฐเซเชฎ"

เช‰เชฆเชพเชนเชฐเชฃ เชคเชฐเซ€เช•เซ‡, เช‰เชชเชฐเซ‹เช•เซเชค เช•เชพเชฐเซเชฏเชจเซ‡ เชธเช‚เชถเซ‹เชงเชฟเชค เช•เชฐเซ€เชจเซ‡, เชคเซ‡เชฎเชจเชพ เชนเซ‡เชคเซเชจเซ‡ เชงเซเชฏเชพเชจเชฎเชพเช‚ เชฒเซ€เชงเชพ เชตเชฟเชจเชพ, เชชเซเชฐเช•เซเชฐเชฟเชฏเชพ เชฎเชพเชŸเซ‡ เชชเซเชฐเชฅเชฎ 20 เชธเซŒเชฅเซ€ เชœเซ‚เชจเซ€ "เชœเชŸเชฟเชฒ" เชตเชฟเชจเช‚เชคเซ€เช“ เชฌเชคเชพเชตเซ‹.

เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เช“เชณเช–เชตเซเช‚

-> Seq Scan | Bitmap Heap Scan | Index [Only] Scan [Backward]
   && 5 ร— rows < RRbF -- ะพั‚ั„ะธะปัŒั‚ั€ะพะฒะฐะฝะพ >80% ะฟั€ะพั‡ะธั‚ะฐะฝะฝะพะณะพ
   && loops ร— RRbF > 100 -- ะธ ะฟั€ะธ ัั‚ะพะผ ะฑะพะปัŒัˆะต 100 ะทะฐะฟะธัะตะน ััƒะผะผะฐั€ะฝะพ

เชญเชฒเชพเชฎเชฃเซ‹

[เชตเชงเซ] เชตเชฟเชถเชฟเชทเซเชŸ เชฌเชจเชพเชตเซ‹ WHERE เชถเชฐเชค เชธเชพเชฅเซ‡ เช…เชจเซเช•เซเชฐเชฎเชฃเชฟเช•เชพ เช…เชฅเชตเชพ เช…เชจเซเช•เซเชฐเชฎเชฃเชฟเช•เชพเชฎเชพเช‚ เชตเชงเชพเชฐเชพเชจเชพ เช•เซเชทเซ‡เชคเซเชฐเซ‹เชจเซ‹ เชธเชฎเชพเชตเซ‡เชถ เช•เชฐเซ‹.

เชœเซ‹ เชคเชฎเชพเชฐเชพ เชนเซ‡เชคเซเช“ เชฎเชพเชŸเซ‡ เชซเชฟเชฒเซเชŸเชฐเชจเซ€ เชธเซเชฅเชฟเชคเชฟ "เชธเซเชฅเชฟเชฐ" เช›เซ‡ - เชคเซ‡ เช›เซ‡ เชตเชฟเชธเซเชคเชฐเชฃ เชธเซ‚เชšเชฟเชค เช•เชฐเชคเซเช‚ เชจเชฅเซ€ เชญเชตเชฟเชทเซเชฏเชฎเชพเช‚ เชฎเซ‚เชฒเซเชฏเซ‹เชจเซ€ เชธเซ‚เชšเชฟ - WHERE เช‡เชจเซเชกเซ‡เช•เซเชธเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเชตเซ‹ เชตเชงเซ เชธเชพเชฐเซเช‚ เช›เซ‡. เชตเชฟเชตเชฟเชง เชฌเซเชฒเชฟเชฏเชจ/เชเชจเชฎ เชธเซเชŸเซ‡เชŸเชธ เช† เช•เซ‡เชŸเซ‡เช—เชฐเซ€เชฎเชพเช‚ เชธเชพเชฐเซ€ เชฐเซ€เชคเซ‡ เชฌเช‚เชงเชฌเซ‡เชธเซ‡ เช›เซ‡.

เชœเซ‹ เชซเชฟเชฒเซเชŸเชฐเชฟเช‚เช— เชธเซเชฅเชฟเชคเชฟ เชตเชฟเชตเชฟเชง เช…เชฐเซเชฅเซ‹ เชฒเชˆ เชถเช•เซ‡ เช›เซ‡, เชคเซ‹ เชชเช›เซ€ เช† เช•เซเชทเซ‡เชคเซเชฐเซ‹ เชธเชพเชฅเซ‡ เช‡เชจเซเชกเซ‡เช•เซเชธเชจเซ‡ เชตเชฟเชธเซเชคเซƒเชค เช•เชฐเชตเซเช‚ เชตเชงเซ เชธเชพเชฐเซเช‚ เช›เซ‡ - เชœเซ‡เชฎ เช•เซ‡ Bitmap เช…เชจเซ‡ เช‰เชชเชฐเชจเซ€ เชชเชฐเชฟเชธเซเชฅเชฟเชคเชฟเชฎเชพเช‚.

เช‰เชฆเชพเชนเชฐเชฃ:

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;

เชฌเซ€เชฎเชพเชฐ SQL เชชเซเชฐเชถเซเชจเซ‹ เชฎเชพเชŸเซ‡ เชตเชพเชจเช—เซ€เช“
[explan.tensor.ru เชชเชฐ เชœเซเช“]

เชธเซเชงเชพเชฐเซ€ เชฐเชนเซเชฏเซเช‚ เช›เซ‡:

CREATE INDEX ON tbl(pk)
  WHERE critical; -- ะดะพะฑะฐะฒะธะปะธ "ัั‚ะฐั‚ะธั‡ะฝะพะต" ัƒัะปะพะฒะธะต ั„ะธะปัŒั‚ั€ะฐั†ะธะธ

เชฌเซ€เชฎเชพเชฐ SQL เชชเซเชฐเชถเซเชจเซ‹ เชฎเชพเชŸเซ‡ เชตเชพเชจเช—เซ€เช“
[explan.tensor.ru เชชเชฐ เชœเซเช“]

เชœเซ‡เชฎ เชคเชฎเซ‡ เชœเซ‹เชˆ เชถเช•เซ‹ เช›เซ‹, เชซเชฟเชฒเซเชŸเชฐเชฟเช‚เช— เชฏเซ‹เชœเชจเชพเชฎเชพเช‚เชฅเซ€ เชธเช‚เชชเซ‚เชฐเซเชฃเชชเชฃเซ‡ เช…เชฆเซƒเชถเซเชฏ เชฅเชˆ เช—เชฏเซเช‚ เช›เซ‡, เช…เชจเซ‡ เชตเชฟเชจเช‚เชคเซ€ เชฌเชจเซ€ เช—เชˆ เช›เซ‡ 5 เช—เชฃเซ€ เชเชกเชชเซ€.

#5: เชธเซเชชเชพเชฐเซเชธ เชŸเซ‡เชฌเชฒ

เชœเซเชฏเชพเชฐเซ‡ เช‰เชฆเชญเชตเซ‡ เช›เซ‡

เชคเชฎเชพเชฐเซ€ เชชเซ‹เชคเชพเชจเซ€ เชŸเชพเชธเซเช• เชชเซเชฐเซ‹เชธเซ‡เชธเชฟเช‚เช— เช•เชคเชพเชฐ เชฌเชจเชพเชตเชตเชพเชจเชพ เชตเชฟเชตเชฟเชง เชชเซเชฐเชฏเชพเชธเซ‹, เชœเซเชฏเชพเชฐเซ‡ เชŸเซ‡เชฌเชฒ เชชเชฐ เชฎเซ‹เชŸเซ€ เชธเช‚เช–เซเชฏเชพเชฎเชพเช‚ เช…เชชเชกเซ‡เชŸเซเชธ/เชกเชฟเชฒเซ€เชŸ เชฅเชคเชพ เชฐเซ‡เช•เซ‹เชฐเซเชกเซเชธ เชฎเซ‹เชŸเซ€ เชธเช‚เช–เซเชฏเชพเชฎเชพเช‚ โ€œเชฎเซƒเชคโ€ เชฐเซ‡เช•เซ‹เชฐเซเชกเชจเซ€ เชธเซเชฅเชฟเชคเชฟ เชคเชฐเชซ เชฆเซ‹เชฐเซ€ เชœเชพเชฏ เช›เซ‡.

เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เช“เชณเช–เชตเซเช‚

-> Seq Scan | Bitmap Heap Scan | Index [Only] Scan [Backward]
   && loops ร— (rows + RRbF) < (shared hit + shared read) ร— 8
      -- ะฟั€ะพั‡ะธั‚ะฐะฝะพ ะฑะพะปัŒัˆะต 1KB ะฝะฐ ะบะฐะถะดัƒัŽ ะทะฐะฟะธััŒ
   && shared hit + shared read > 64

เชญเชฒเชพเชฎเชฃเซ‹

เชจเชฟเชฏเชฎเชฟเชคเชชเชฃเซ‡ เชœเชพเชคเซ‡ เชนเชพเชฅ เชงเชฐเซ‡ เช›เซ‡ เชตเซ‡เช•เซเชฏเซเชฎ [เชชเซ‚เชฐเซเชฃ] เช…เชฅเชตเชพ เชชเชฐเซเชฏเชพเชชเซเชค เชตเชพเชฐเช‚เชตเชพเชฐ เชคเชพเชฒเซ€เชฎ เชชเซเชฐเชพเชชเซเชค เช•เชฐเซ‹ เช“เชŸเซ‹เชตเซ‡เช•เซเชฏเซเชฎ เชคเซ‡เชจเชพ เชชเชฐเชฟเชฎเชพเชฃเซ‹เชจเซ‡ เชซเชพเช‡เชจ-เชŸเซเชฏเซเชจเชฟเช‚เช— เช•เชฐเซ€เชจเซ‡, เชธเชนเชฟเชค เชšเซ‹เช•เซเช•เชธ เชŸเซ‡เชฌเชฒ เชฎเชพเชŸเซ‡.

เชฎเซ‹เชŸเชพ เชญเชพเช—เชจเชพ เช•เชฟเชธเซเชธเชพเช“เชฎเชพเช‚, เช†เชตเซ€ เชธเชฎเชธเซเชฏเชพเช“ เชจเชฌเชณเซ€ เช•เซเชตเซ‡เชฐเซ€ เช•เชฎเซเชชเซ‹เชเชฟเชถเชจเชจเซ‡ เช•เชพเชฐเชฃเซ‡ เชฅเชพเชฏ เช›เซ‡ เชœเซเชฏเชพเชฐเซ‡ เชฌเชฟเชเชจเซ‡เชธ เชฒเซ‹เชœเชฟเช•เชฎเชพเช‚เชฅเซ€ เช•เซ‰เชฒ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡ เชœเซ‡เชฎ เช•เซ‡ เชชเซ‹เชธเซเชŸเช—เซเชฐเซ‡เชเชธเช•เซเชฏเซเชเชฒ เชเชจเซเชŸเชฟเชชเซ‡เชŸเชฐเซเชจ: "เชฎเซƒเชค" เชจเซ€ เชฒเชกเชพเชˆ.

เชชเชฐเช‚เชคเซ เชคเชฎเชพเชฐเซ‡ เช เชธเชฎเชœเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡ เช•เซ‡ VACUUM FULL เชนเช‚เชฎเซ‡เชถเชพ เชฎเชฆเชฆ เช•เชฐเซ€ เชถเช•เชคเซเช‚ เชจเชฅเซ€. เช†เชตเชพ เช•เชฟเชธเซเชธเชพเช“ เชฎเชพเชŸเซ‡, เชฒเซ‡เช–เชฎเชพเช‚เชฅเซ€ เช…เชฒเซเช—เซ‹เชฐเชฟเชงเชฎเชจเซ‹ เชธเชพเชฅเซ‡ เชชเซ‹เชคเชพเชจเซ‡ เชชเชฐเชฟเชšเชฟเชค เช•เชฐเชตเชพ เชฏเซ‹เช—เซเชฏ เช›เซ‡ DBA: เชœเซเชฏเชพเชฐเซ‡ VACUUM เชจเชฟเชทเซเชซเชณ เชœเชพเชฏ เช›เซ‡, เชคเซเชฏเชพเชฐเซ‡ เช…เชฎเซ‡ เชŸเซ‡เชฌเชฒ เชœเชพเชคเซ‡ เชธเชพเชซ เช•เชฐเซ€เช เช›เซ€เช.

#6: เช…เชจเซเช•เซเชฐเชฎเชฃเชฟเช•เชพเชจเชพ "เชฎเชงเซเชฏเชฎ" เชฎเชพเช‚เชฅเซ€ เชตเชพเช‚เชšเชจ

เชœเซเชฏเชพเชฐเซ‡ เช‰เชฆเชญเชตเซ‡ เช›เซ‡

เชเชตเซเช‚ เชฒเชพเช—เซ‡ เช›เซ‡ เช•เซ‡ เช…เชฎเซ‡ เชฅเซ‹เชกเซเช‚ เชตเชพเช‚เชšเซเชฏเซเช‚ เช›เซ‡, เช…เชจเซ‡ เชฌเชงเซเช‚ เช…เชจเซเช•เซเชฐเชฎเชฟเชค เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซเชฏเซเช‚ เชนเชคเซเช‚, เช…เชจเซ‡ เช…เชฎเซ‡ เช•เซ‹เชˆเชจเซ‡ เชตเชงเซ เชซเชฟเชฒเซเชŸเชฐ เช•เชฐเซเชฏเซเช‚ เชจเชฅเซ€ - เชชเชฐเช‚เชคเซ เชคเซ‡เชฎ เช›เชคเชพเช‚ เช…เชฎเซ‡ เช…เชฎเชพเชฐเซ€ เช‡เชšเซเช›เชพ เช•เชฐเชคเชพเช‚ เชจเซ‹เช‚เชงเชชเชพเชคเซเชฐ เชฐเซ€เชคเซ‡ เชตเชงเซ เชชเซƒเชทเซเช เซ‹ เชตเชพเช‚เชšเซ€เช เช›เซ€เช.

เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เช“เชณเช–เชตเซเช‚

-> 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;

เชฌเซ€เชฎเชพเชฐ SQL เชชเซเชฐเชถเซเชจเซ‹ เชฎเชพเชŸเซ‡ เชตเชพเชจเช—เซ€เช“
[explan.tensor.ru เชชเชฐ เชœเซเช“]

เช…เชจเซเช•เซเชฐเชฎเชฃเชฟเช•เชพ เชฎเซเชœเชฌ เชชเชฃ เชฌเชงเซเช‚ เชธเชพเชฐเซเช‚ เชฒเชพเช—เซ‡ เช›เซ‡, เชชเชฐเช‚เชคเซ เชคเซ‡ เช•เซ‹เชˆเช• เชฐเซ€เชคเซ‡ เชถเช‚เช•เชพเชธเซเชชเชฆ เช›เซ‡ - เชตเชพเช‚เชšเซ‡เชฒเชพ 20 เชฐเซ‡เช•เซ‹เชฐเซเชกเซเชธเชฎเชพเช‚เชฅเซ€ เชฆเชฐเซ‡เช• เชฎเชพเชŸเซ‡, เช…เชฎเชพเชฐเซ‡ เชฐเซ‡เช•เซ‹เชฐเซเชก เชฆเซ€เช  4KB เชกเซ‡เชŸเชพเชจเชพ 32 เชชเซƒเชทเซเช เซ‹เชจเซ‡ เชฌเชพเชฆ เช•เชฐเชตเซ‹ เชชเชกเซเชฏเซ‹ - เชถเซเช‚ เชคเซ‡ เชฌเซ‹เชฒเซเชก เชจเชฅเซ€? เช…เชจเซ‡ เช‡เชจเซเชกเซ‡เช•เซเชธ เชจเชพเชฎ tbl_fk_org_fk_cli_idx เชตเชฟเชšเชพเชฐเชชเซเชฐเซ‡เชฐเช•.

เชธเซเชงเชพเชฐเซ€ เชฐเชนเซเชฏเซเช‚ เช›เซ‡:

CREATE INDEX ON tbl(fk_cli);

เชฌเซ€เชฎเชพเชฐ SQL เชชเซเชฐเชถเซเชจเซ‹ เชฎเชพเชŸเซ‡ เชตเชพเชจเช—เซ€เช“
[explan.tensor.ru เชชเชฐ เชœเซเช“]

เช…เชšเชพเชจเช• - 10 เช—เชฃเซ€ เชเชกเชชเซ€ เช…เชจเซ‡ เชตเชพเช‚เชšเชตเชพ เชฎเชพเชŸเซ‡ 4 เช—เชฃเซ€ เช“เช›เซ€!

เช…เชจเซเช•เซเชฐเชฎเชฃเชฟเช•เชพเช“เชจเชพ เชฌเชฟเชจเช…เชธเชฐเช•เชพเชฐเช• เช‰เชชเชฏเซ‹เช—เชจเซ€ เชชเชฐเชฟเชธเซเชฅเชฟเชคเชฟเช“เชจเชพ เช…เชจเซเชฏ เช‰เชฆเชพเชนเชฐเชฃเซ‹ เชฒเซ‡เช–เชฎเชพเช‚ เชœเซ‹เชˆ เชถเช•เชพเชฏ เช›เซ‡ DBA: เชจเช•เชพเชฎเซ€ เช…เชจเซเช•เซเชฐเชฎเชฃเชฟเช•เชพเช“ เชถเซ‹เชงเชตเซ€.

#7: CTE ร— CTE

เชœเซเชฏเชพเชฐเซ‡ เช‰เชฆเชญเชตเซ‡ เช›เซ‡

เชตเชฟเชจเช‚เชคเซ€เชฎเชพเช‚ เชธเซเช•เซ‹เชฐ โ€œเชšเชฐเชฌเซ€โ€ CTE เชตเชฟเชตเชฟเชง เช•เซ‹เชทเซเชŸเช•เซ‹เชฎเชพเช‚เชฅเซ€, เช…เชจเซ‡ เชชเช›เซ€ เชคเซ‡เชฎเชจเซ€ เชตเชšเซเชšเซ‡ เชคเซ‡ เช•เชฐเชตเชพเชจเซเช‚ เชจเช•เซเช•เซ€ เช•เชฐเซเชฏเซเช‚ JOIN.

เช•เซ‡เชธ v12 เชจเซ€ เชจเซ€เชšเซ‡เชจเชพ เชธเช‚เชธเซเช•เชฐเชฃเซ‹ เช…เชฅเชตเชพ เชธเชพเชฅเซ‡เชจเซ€ เชตเชฟเชจเช‚เชคเซ€เช“ เชฎเชพเชŸเซ‡ เชธเช‚เชฌเช‚เชงเชฟเชค เช›เซ‡ WITH MATERIALIZED.

เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เช“เชณเช–เชตเซเช‚

-> CTE Scan
   && loops > 10
   && loops ร— (rows + RRbF) > 10000
      -- ัะปะธัˆะบะพะผ ะฑะพะปัŒัˆะพะต ะดะตะบะฐั€ั‚ะพะฒะพ ะฟั€ะพะธะทะฒะตะดะตะฝะธะต CTE

เชญเชฒเชพเชฎเชฃเซ‹

เชตเชฟเชจเช‚เชคเซ€เชจเซเช‚ เช•เชพเชณเชœเซ€เชชเซ‚เชฐเซเชตเช• เชตเชฟเชถเซเชฒเซ‡เชทเชฃ เช•เชฐเซ‹ - เช…เชจเซ‡ เชถเซเช‚ เช…เชนเซ€เช‚ CTE เชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡?? เชœเซ‹ เชนเชพ, เชคเซ‹ hstore/json เชฎเชพเช‚ "เชถเชฌเซเชฆเช•เซ‹เชท" เชฒเชพเช—เซ เช•เชฐเซ‹ เชฎเชพเช‚ เชตเชฐเซเชฃเชตเซ‡เชฒ เชฎเซ‹เชกเซ‡เชฒ เช…เชจเซเชธเชพเชฐ PostgreSQL เชเชจเซเชŸเชฟเชชเซ‡เชŸเชฐเซเชจ: เชกเชฟเช•เซเชถเชจเชฐเซ€ เชนเชฟเชŸ เชนเซ‡เชตเซ€ เชœเซ‹เช‡เชจ.

#8: เชกเชฟเชธเซเช• เชชเชฐ เชธเซเชตเซ‡เชช (เชŸเซ‡เชฎเซเชชเชฒ เชฒเช–เซ‡เชฒเซเช‚)

เชœเซเชฏเชพเชฐเซ‡ เช‰เชฆเชญเชตเซ‡ เช›เซ‡

เชฎเซ‹เชŸเซ€ เชธเช‚เช–เซเชฏเชพเชฎเชพเช‚ เชฐเซ‡เช•เซ‹เชฐเซเชกเซเชธเชจเซเช‚ เชตเชจ-เชŸเชพเช‡เชฎ เชชเซเชฐเซ‹เชธเซ‡เชธเชฟเช‚เช— (เชธเซ‰เชฐเซเชŸเชฟเช‚เช— เช…เชฅเชตเชพ เชฏเซเชจเชฟเช•เชพเช‡เชเซ‡เชถเชจ) เช† เชฎเชพเชŸเซ‡ เชซเชพเชณเชตเชตเชพเชฎเชพเช‚ เช†เชตเซ‡เชฒเซ€ เชฎเซ‡เชฎเชฐเซ€เชฎเชพเช‚ เชซเชฟเชŸ เชฅเชคเซเช‚ เชจเชฅเซ€.

เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เช“เชณเช–เชตเซเช‚

-> *
   && temp written > 0

เชญเชฒเชพเชฎเชฃเซ‹

เชœเซ‹ เช“เชชเชฐเซ‡เชถเชจ เชฆเซเชตเชพเชฐเชพ เช‰เชชเชฏเซ‹เช—เชฎเชพเช‚ เชฒเซ‡เชตเชพเชคเซ€ เชฎเซ‡เชฎเชฐเซ€เชจเซ€ เชฎเชพเชคเซเชฐเชพ เชชเซ‡เชฐเชพเชฎเซ€เชŸเชฐเชจเชพ เช‰เชฒเซเชฒเซ‡เช–เชฟเชค เชฎเซ‚เชฒเซเชฏ เช•เชฐเชคเชพเช‚ เชฎเซ‹เชŸเชพ เชชเซเชฐเชฎเชพเชฃเชฎเชพเช‚ เชตเชงเซ€ เชจเชฅเซ€ เชตเชฐเซเช•_เชฎเซ‡เชฎ, เชคเซ‡ เชธเซเชงเชพเชฐเชตเชพ เชตเชฐเซเชฅ เช›เซ‡. เชคเชฎเซ‡ เชคเชฐเชค เชœ เชฆเชฐเซ‡เช• เชฎเชพเชŸเซ‡ เชฐเซ‚เชชเชฐเซ‡เช–เชพเชฎเชพเช‚ เช•เชฐเซ€ เชถเช•เซ‹ เช›เซ‹, เช…เชฅเชตเชพ เชคเชฎเซ‡ เช•เชฐเซ€ เชถเช•เซ‹ เช›เซ‹ SET [LOCAL] เชšเซ‹เช•เซเช•เชธ เชตเชฟเชจเช‚เชคเซ€/เชตเซเชฏเชตเชนเชพเชฐ เชฎเชพเชŸเซ‡.

เช‰เชฆเชพเชนเชฐเชฃ:

SHOW work_mem;
-- "16MB"

SELECT
  random()
FROM
  generate_series(1, 1000000)
ORDER BY
  1;

เชฌเซ€เชฎเชพเชฐ SQL เชชเซเชฐเชถเซเชจเซ‹ เชฎเชพเชŸเซ‡ เชตเชพเชจเช—เซ€เช“
[explan.tensor.ru เชชเชฐ เชœเซเช“]

เชธเซเชงเชพเชฐเซ€ เชฐเชนเซเชฏเซเช‚ เช›เซ‡:

SET work_mem = '128MB'; -- ะฟะตั€ะตะด ะฒั‹ะฟะพะปะฝะตะฝะธะตะผ ะทะฐะฟั€ะพัะฐ

เชฌเซ€เชฎเชพเชฐ SQL เชชเซเชฐเชถเซเชจเซ‹ เชฎเชพเชŸเซ‡ เชตเชพเชจเช—เซ€เช“
[explan.tensor.ru เชชเชฐ เชœเซเช“]

เชธเซเชชเชทเซเชŸ เช•เชพเชฐเชฃเซ‹เชธเชฐ, เชœเซ‹ เชซเช•เซเชค เชฎเซ‡เชฎเชฐเซ€เชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡ เช…เชจเซ‡ เชกเชฟเชธเซเช•เชจเซ‹ เช‰เชชเชฏเซ‹เช— เชฅเชคเซ‹ เชจเชฅเซ€, เชคเซ‹ เช•เซเชตเซ‡เชฐเซ€ เชตเชงเซ เชเชกเชชเชฅเซ€ เชšเชฒเชพเชตเชตเชพเชฎเชพเช‚ เช†เชตเชถเซ‡. เชคเซ‡ เชœ เชธเชฎเชฏเซ‡, เชเชšเชกเซ€เชกเซ€เชฎเชพเช‚เชฅเซ€ เชฒเซ‹เชกเชจเซ‹ เชญเชพเช— เชชเชฃ เชฆเซ‚เชฐ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡.

เชชเชฐเช‚เชคเซ เชคเชฎเชพเชฐเซ‡ เช เชธเชฎเชœเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡ เช•เซ‡ เชคเชฎเซ‡ เชนเช‚เชฎเซ‡เชถเชพ เช˜เชฃเซ€ เชฌเชงเซ€ เช…เชจเซ‡ เช˜เชฃเซ€ เชฌเชงเซ€ เชฎเซ‡เชฎเชฐเซ€ เชซเชพเชณเชตเซ€ เชถเช•เชถเซ‹ เชจเชนเซ€เช‚ - เชคเซ‡ เชฆเชฐเซ‡เช• เชฎเชพเชŸเซ‡ เชชเซ‚เชฐเชคเซเช‚ เชจเชฅเซ€.

#9: เช…เชชเซเชฐเชธเซเชคเซเชค เช†เช‚เช•เชกเชพ

เชœเซเชฏเชพเชฐเซ‡ เช‰เชฆเชญเชตเซ‡ เช›เซ‡

เชคเซ‡เช“เช เชเช• เชœ เชธเชฎเชฏเซ‡ เชกเซ‡เชŸเชพเชฌเซ‡เชเชฎเชพเช‚ เช˜เชฃเซเช‚ เชฌเชงเซเช‚ เชฐเซ‡เชกเซเชฏเซเช‚, เชชเชฐเช‚เชคเซ เชคเซ‡เชจเซ‡ เชฆเซ‚เชฐ เช•เชฐเชตเชพเชจเซ‹ เชธเชฎเชฏ เชจเชนเซ‹เชคเซ‹ ANALYZE.

เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เช“เชณเช–เชตเซเช‚

-> Seq Scan | Bitmap Heap Scan | Index [Only] Scan [Backward]
   && ratio >> 10

เชญเชฒเชพเชฎเชฃเซ‹

เชคเซ‡เชจเซ‡ เชฌเชนเชพเชฐ เชฒเชˆ เชœเชพเช“ ANALYZE.

เช† เชชเชฐเชฟเชธเซเชฅเชฟเชคเชฟเชฎเชพเช‚ เชตเชงเซ เชตเชฟเช—เชคเชตเชพเชฐ เชตเชฐเซเชฃเชตเซ‡เชฒ เช›เซ‡ PostgreSQL เชเชจเซเชŸเชฟเชชเซ‡เชŸเชฐเซเชจ: เช†เช‚เช•เชกเชพ เชฌเชงเซเช‚ เชœ เช›เซ‡.

#10: "เช•เช‚เชˆเช• เช–เซ‹เชŸเซเช‚ เชฅเชฏเซเช‚"

เชœเซเชฏเชพเชฐเซ‡ เช‰เชฆเชญเชตเซ‡ เช›เซ‡

เชธเซเชชเชฐเซเชงเชพเชคเซเชฎเช• เชตเชฟเชจเช‚เชคเชฟ เชฆเซเชตเชพเชฐเชพ เชฒเชพเชฆเชตเชพเชฎเชพเช‚ เช†เชตเซ‡เชฒ เชฒเซ‰เช•เชจเซ€ เชฐเชพเชน เชœเซ‹เชตเชพเชˆ เชฐเชนเซ€ เชนเชคเซ€, เช…เชฅเชตเชพ เชคเซเชฏเชพเช‚ เช…เชชเซ‚เชฐเชคเชพ CPU/เชนเชพเชฏเชชเชฐเชตเชพเชˆเชเชฐ เชนเชพเชฐเซเชกเชตเซ‡เชฐ เชธเช‚เชธเชพเชงเชจเซ‹ เชนเชคเชพ.

เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เช“เชณเช–เชตเซเช‚

-> *
   && (shared hit / 8K) + (shared read / 1K) < time / 1000
      -- RAM hit = 64MB/s, HDD read = 8MB/s
   && time > 100ms -- ั‡ะธั‚ะฐะปะธ ะผะฐะปะพ, ะฝะพ ัะปะธัˆะบะพะผ ะดะพะปะณะพ

เชญเชฒเชพเชฎเชฃเซ‹

เชฌเชพเชนเซเชฏ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ‹ เชฎเซ‹เชจเซ€เชŸเชฐเซ€เช‚เช— เชธเชฟเชธเซเชŸเชฎ เช…เชตเชฐเซ‹เชงเชฟเชค เช…เชฅเชตเชพ เช…เชธเชพเชฎเชพเชจเซเชฏ เชธเช‚เชธเชพเชงเชจ เชตเชชเชฐเชพเชถ เชฎเชพเชŸเซ‡ เชธเชฐเซเชตเชฐ. เช…เชฎเซ‡ เชธเซ‡เช‚เช•เชกเซ‹ เชธเชฐเซเชตเชฐเซเชธ เชฎเชพเชŸเซ‡ เช† เชชเซเชฐเช•เซเชฐเชฟเชฏเชพเชจเซ‡ เช—เซ‹เช เชตเชตเชพเชจเชพ เช…เชฎเชพเชฐเชพ เชธเช‚เชธเซเช•เชฐเชฃ เชตเชฟเชถเซ‡ เชชเชนเซ‡เชฒเซ‡เชฅเซ€ เชœ เชตเชพเชค เช•เชฐเซ€ เช›เซ‡ เช…เชนเซ€เช‚ ะธ เช…เชนเซ€เช‚.

เชฌเซ€เชฎเชพเชฐ SQL เชชเซเชฐเชถเซเชจเซ‹ เชฎเชพเชŸเซ‡ เชตเชพเชจเช—เซ€เช“
เชฌเซ€เชฎเชพเชฐ SQL เชชเซเชฐเชถเซเชจเซ‹ เชฎเชพเชŸเซ‡ เชตเชพเชจเช—เซ€เช“

เชธเซ‹เชฐเซเชธ: www.habr.com

เชเช• เชŸเชฟเชชเซเชชเชฃเซ€ เช‰เชฎเซ‡เชฐเซ‹