เจฌเฉ€เจฎเจพเจฐ 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 เจธเจตเจพเจฒเจพเจ‚ เจฒเจˆ เจชเจ•เจตเจพเจจเจพเจ‚
[explanation.tensor.ru 'เจคเฉ‡ เจฆเฉ‡เจ–เฉ‹]

เจคเฉเจธเฉ€เจ‚ เจคเฉเจฐเฉฐเจค เจจเฉ‹เจŸเจฟเจธ เจ•เจฐ เจธเจ•เจฆเฉ‡ เจนเฉ‹ เจ•เจฟ เจธเฉ‚เจšเจ•เจพเจ‚เจ• เจคเฉ‹เจ‚ 100 เจคเฉ‹เจ‚ เจตเฉฑเจง เจฐเจฟเจ•เจพเจฐเจกเจพเจ‚ เจจเฉ‚เฉฐ เจ˜เจŸเจพ เจฆเจฟเฉฑเจคเจพ เจ—เจฟเจ† เจธเฉ€, เจœเฉ‹ เจซเจฟเจฐ เจธเจพเจฐเฉ‡ เจ•เฉเจฐเจฎเจฌเฉฑเจง เจ•เฉ€เจคเฉ‡ เจ—เจ เจธเจจ, เจ…เจคเฉ‡ เจซเจฟเจฐ เจธเจฟเจฐเจซเจผ เจ‡เฉฑเจ• เจนเฉ€ เจฌเจšเจฟเจ† เจธเฉ€เฅค

เจ เฉ€เจ• เจ•เจฐเจจเจพ:

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

เจฌเฉ€เจฎเจพเจฐ SQL เจธเจตเจพเจฒเจพเจ‚ เจฒเจˆ เจชเจ•เจตเจพเจจเจพเจ‚
[explanation.tensor.ru 'เจคเฉ‡ เจฆเฉ‡เจ–เฉ‹]

เจ…เจœเจฟเจนเฉ‡ เจ†เจฆเจฟเจฎ เจจเจฎเฉ‚เจจเฉ‡ 'เจคเฉ‡ เจตเฉ€ - 8.5 เจ—เฉเจฃเจพ เจคเฉ‡เจœเจผ เจ…เจคเฉ‡ 33 เจ—เฉเจฃเจพ เจ˜เฉฑเจŸ เจชเฉœเฉเจนเจฟเจ† เจœเจพเจ‚เจฆเจพ เจนเฉˆ. เจนเจฐเฉ‡เจ• เจฎเฉเฉฑเจฒ เจฒเจˆ เจคเฉเจนเจพเจกเฉ‡ เจ•เฉ‹เจฒ เจœเจฟเฉฐเจจเฉ‡ เจœเจผเจฟเจ†เจฆเจพ "เจคเฉฑเจฅ" เจนเฉ‹เจฃเจ—เฉ‡, เจชเฉเจฐเจญเจพเจต เจ“เจจเจพ เจนเฉ€ เจธเจชเฉฑเจธเจผเจŸ เจนเฉ‹เจตเฉ‡เจ—เจพ fk.

เจฎเฉˆเจ‚ เจจเฉ‹เจŸ เจ•เจฐเจฆเจพ เจนเจพเจ‚ เจ•เจฟ เจ…เจœเจฟเจนเจพ เจธเฉ‚เจšเจ•เจพเจ‚เจ• เจ‡เฉฑเจ• "เจ…เจ—เฉ‡เจคเจฐ" เจธเฉ‚เจšเจ•เจพเจ‚เจ• เจฆเฉ‡ เจคเฉŒเจฐ เจคเฉ‡ เจ•เฉฐเจฎ เจ•เจฐเฉ‡เจ—เจพ, เจœเจฟเจธ เจจเจพเจฒ เจนเฉ‹เจฐ เจชเฉเฉฑเจ›เจ—เจฟเฉฑเจ›เจพเจ‚ เจฒเจˆ เจชเจนเจฟเจฒเจพเจ‚ เจจเจพเจฒเฉ‹เจ‚ เจฎเจพเฉœเจพ เจจเจนเฉ€เจ‚ เจนเฉ‹เจตเฉ‡เจ—เจพ fk, เจœเจฟเฉฑเจฅเฉ‡ เจฆเฉเจ†เจฐเจพ เจ•เฉเจฐเจฎเจฌเฉฑเจง pk เจ‰เฉฑเจฅเฉ‡ เจจเจนเฉ€เจ‚ เจธเฉ€ เจ…เจคเฉ‡ เจ‰เฉฑเจฅเฉ‡ เจจเจนเฉ€เจ‚ เจนเฉˆ (เจคเฉเจธเฉ€เจ‚ เจ‡เจธ เจฌเจพเจฐเฉ‡ เจนเฉ‹เจฐ เจชเฉœเฉเจน เจธเจ•เจฆเฉ‡ เจนเฉ‹ เจฌเฉ‡เจ…เจธเจฐ เจธเฉ‚เจšเจ•เจพเจ‚เจ• เจฒเฉฑเจญเจฃ เจฌเจพเจฐเฉ‡ เจฎเฉ‡เจฐเฉ‡ เจฒเฉ‡เจ– เจตเจฟเฉฑเจš). เจธเจฎเฉ‡เจค, เจ‡เจน เจ†เจฎ เจชเฉเจฐเจฆเจพเจจ เจ•เจฐเฉ‡เจ—เจพ เจธเจชเจธเจผเจŸ เจตเจฟเจฆเฉ‡เจธเจผเฉ€ เจ•เฉเฉฐเจœเฉ€ เจธเจฎเจฐเจฅเจจ เจ‡เจธ เจ–เฉ‡เจคเจฐ 'เจคเฉ‡.

#2: เจ‡เฉฐเจกเฉˆเจ•เจธ เจ‡เฉฐเจŸเจฐเจธเฉˆเจ•เจธเจผเจจ (เจฌเจฟเจŸเจฎเฉˆเจช เจ…เจคเฉ‡)

เจ•เจฆเฉ‹เจ‚ เจ•เจฐเจฆเจพ เจนเฉˆ

เจ•เจฒเจพเจ‡เฉฐเจŸ "LLC เจ•เฉ‹เจฒเฉ‹เจ•เฉ‹เจฒเจšเจฟเจ•" เจฒเจˆ เจธเจพเจฐเฉ‡ เจธเจฎเจเฉŒเจคเฉ‡ เจฆเจฟเจ–เจพเจ“, "NAO เจฌเจŸเจฐเจ•เฉฑเจช" เจฆเฉ€ เจคเจฐเจซเฉ‹เจ‚ เจธเจฎเจพเจชเจค เจนเฉ‹เจเฅค

เจชเจ›เจพเจฃ เจ•เจฟเจตเฉ‡เจ‚ เจ•เจฐเฉ€เจ

-> 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 เจธเจตเจพเจฒเจพเจ‚ เจฒเจˆ เจชเจ•เจตเจพเจจเจพเจ‚
[explanation.tensor.ru 'เจคเฉ‡ เจฆเฉ‡เจ–เฉ‹]

เจ เฉ€เจ• เจ•เจฐเจจเจพ:

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

เจฌเฉ€เจฎเจพเจฐ SQL เจธเจตเจพเจฒเจพเจ‚ เจฒเจˆ เจชเจ•เจตเจพเจจเจพเจ‚
[explanation.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 เจธเจตเจพเจฒเจพเจ‚ เจฒเจˆ เจชเจ•เจตเจพเจจเจพเจ‚
[explanation.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 เจธเจตเจพเจฒเจพเจ‚ เจฒเจˆ เจชเจ•เจตเจพเจจเจพเจ‚
[explanation.tensor.ru 'เจคเฉ‡ เจฆเฉ‡เจ–เฉ‹]

เจ…เจธเฉ€เจ‚ เจ‡เจธ เจคเฉฑเจฅ เจฆเจพ เจซเจพเจ‡เจฆเจพ เจ‰เจ เจพเจ‡เจ† เจ•เจฟ เจชเจนเจฟเจฒเฉ‡ เจฌเจฒเจพเจ• เจตเจฟเฉฑเจš เจธเจพเจฐเฉ‡ 20 เจฒเฉ‹เฉœเฉ€เจ‚เจฆเฉ‡ เจฐเจฟเจ•เจพเจฐเจก เจคเฉเจฐเฉฐเจค เจชเฉเจฐเจพเจชเจค เจ•เฉ€เจคเฉ‡ เจ—เจ เจธเจจ, เจ‡เจธเจฒเจˆ เจฆเฉ‚เจœเจพ, เจตเจงเฉ‡เจฐเฉ‡ "เจฎเจนเจฟเฉฐเจ—เฉ‡" เจฌเจฟเจŸเจฎเฉˆเจช เจนเฉ€เจช เจธเจ•เฉˆเจจ เจฆเฉ‡ เจจเจพเจฒ, เจจเฉ‚เฉฐ เจตเฉ€ เจฒเจพเจ—เฉ‚ เจจเจนเฉ€เจ‚ เจ•เฉ€เจคเจพ เจ—เจฟเจ† เจธเฉ€ - เจ…เฉฐเจค เจตเจฟเฉฑเจš 22 เจ—เฉเจฃเจพ เจคเฉ‡เจœเจผ, 44 เจ—เฉเจฃเจพ เจ˜เฉฑเจŸ เจชเฉœเฉเจนเจฟเจ†!

เจ‡เจธ เจ“เจชเจŸเฉ€เจฎเจพเจˆเจœเฉ‡เจธเจผเจจ เจตเจฟเจงเฉ€ เจฌเจพเจฐเฉ‡ เจ‡เฉฑเจ• เจนเฉ‹เจฐ เจตเจฟเจธเจคเฉเจฐเจฟเจค เจ•เจนเจพเจฃเฉ€ เจ–เจพเจธ เจ‰เจฆเจพเจนเจฐเจฃเจพเจ‚ เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐเจฆเฉ‡ เจนเฉ‹เจ เจฒเฉ‡เจ–เจพเจ‚ เจตเจฟเฉฑเจš เจชเฉœเฉเจนเจฟเจ† เจœเจพ เจธเจ•เจฆเจพ เจนเฉˆ PostgreSQL เจเจ‚เจŸเฉ€เจชเฉˆเจŸเจฐเจจ: เจนเจพเจจเฉ€เจ•เจพเจฐเจ• JOINs เจ…เจคเฉ‡ ORs ะธ PostgreSQL เจเจ‚เจŸเฉ€เจชเฉˆเจŸเจฐเจจเจœเจผ: เจจเจพเจฎ เจฆเฉเจ†เจฐเจพ เจ–เฉ‹เจœ เจฆเฉ‡ เจฆเฉเจนเจฐเจพเจ เจธเฉเจงเจพเจฐ เจฆเฉ€ เจ•เจนเจพเจฃเฉ€, เจœเจพเจ‚ "เจ…เฉฑเจ—เฉ‡ เจ…เจคเฉ‡ เจ…เฉฑเจ—เฉ‡ เจ…เจจเฉเจ•เฉ‚เจฒเจคเจพ".

เจ†เจฎ เจธเฉฐเจธเจ•เจฐเจฃ เจ•เจˆ เจ•เฉเฉฐเจœเฉ€เจ†เจ‚ เจฆเฉ‡ เจ†เจงเจพเจฐ 'เจคเฉ‡ เจ†เจฐเจกเจฐ เจ•เฉ€เจคเฉ€ เจšเฉ‹เจฃ (เจ…เจคเฉ‡ เจจเจพ เจธเจฟเจฐเจซเจผ 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 เจธเฉ‚เจšเจ•เจพเจ‚เจ• เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐเจจเจพ เจฌเจฟเจนเจคเจฐ เจนเฉˆเฅค เจตเฉฑเจ–-เจตเฉฑเจ– เจฌเฉเจฒเฉ€เจ…เจจ/เจเจจเจฎ เจธเจฅเจฟเจคเฉ€เจ†เจ‚ เจ‡เจธ เจธเจผเฉเจฐเฉ‡เจฃเฉ€ เจตเจฟเฉฑเจš เจšเฉฐเจ—เฉ€ เจคเจฐเฉเจนเจพเจ‚ เจซเจฟเฉฑเจŸ เจนเฉเฉฐเจฆเฉ€เจ†เจ‚ เจนเจจเฅค

เจœเฉ‡ เจซเจฟเจฒเจŸเจฐเจฟเฉฐเจ— เจธเจฅเจฟเจคเฉ€ เจตเฉฑเจ–-เจตเฉฑเจ– เจ…เจฐเจฅ เจฒเฉˆ เจธเจ•เจฆเฉ‡ เจนเจจ, เจซเจฟเจฐ เจ‡เจนเจจเจพเจ‚ เจ–เฉ‡เจคเจฐเจพเจ‚ เจฆเฉ‡ เจจเจพเจฒ เจธเฉ‚เจšเจ•เจพเจ‚เจ• เจฆเจพ เจตเจฟเจธเจคเจพเจฐ เจ•เจฐเจจเจพ เจฌเจฟเจนเจคเจฐ เจนเฉˆ - เจœเจฟเจตเฉ‡เจ‚ เจ•เจฟ เจฌเจฟเจŸเจฎเฉˆเจช เจ…เจคเฉ‡ เจ‰เฉฑเจชเจฐ เจฆเฉ€ เจธเจฅเจฟเจคเฉ€ เจตเจฟเฉฑเจš เจนเฉˆเฅค

เจ‰เจฆเจพเจนเจฐเจจ:

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 เจธเจตเจพเจฒเจพเจ‚ เจฒเจˆ เจชเจ•เจตเจพเจจเจพเจ‚
[explanation.tensor.ru 'เจคเฉ‡ เจฆเฉ‡เจ–เฉ‹]

เจ เฉ€เจ• เจ•เจฐเจจเจพ:

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

เจฌเฉ€เจฎเจพเจฐ SQL เจธเจตเจพเจฒเจพเจ‚ เจฒเจˆ เจชเจ•เจตเจพเจจเจพเจ‚
[explanation.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

เจฟเจธเจซเจผเจพเจฐ

เจนเฉฑเจฅเฉ€เจ‚ เจจเจฟเจฏเจฎเจฟเจค เจคเฉŒเจฐ 'เจคเฉ‡ เจ•เจฐเฉ‹ เจตเฉˆเจ•เจฟเจŠเจฎ [เจชเฉ‚เจฐเจพ] เจœเจพเจ‚ เจขเฉเจ•เจตเฉ€เจ‚ เจตเจพเจฐ-เจตเจพเจฐ เจธเจฟเจ–เจฒเจพเจˆ เจชเฉเจฐเจพเจชเจค เจ•เจฐเฉ‹ เจ†เจŸเฉ‹เจตเฉˆเจ•เจฟเจŠเจฎ เจ‡เจธเจฆเฉ‡ เจฎเจพเจชเจฆเฉฐเจกเจพเจ‚ เจจเฉ‚เฉฐ เจตเจงเฉ€เจ†-เจŸเจฟเจŠเจจเจฟเฉฐเจ— เจ•เจฐเจ•เฉ‡, เจธเจฎเฉ‡เจค เจ‡เฉฑเจ• เจ–เจพเจธ เจธเจพเจฐเจฃเฉ€ เจฒเจˆ.

เจœเจผเจฟเจ†เจฆเจพเจคเจฐ เจฎเจพเจฎเจฒเจฟเจ†เจ‚ เจตเจฟเฉฑเจš, เจ…เจœเจฟเจนเฉ€เจ†เจ‚ เจธเจฎเฉฑเจธเจฟเจ†เจตเจพเจ‚ เจ•เจพเจฐเฉ‹เจฌเจพเจฐเฉ€ เจคเจฐเจ• เจคเฉ‹เจ‚ เจ•เจพเจฒ เจ•เจฐเจจ เจตเฉ‡เจฒเฉ‡ เจ–เจฐเจพเจฌ เจชเฉเฉฑเจ›เจ—เจฟเฉฑเจ› เจฒเฉ‡เจ†เจ‰เจŸ เจ•เจพเจฐเจจ เจนเฉเฉฐเจฆเฉ€เจ†เจ‚ เจนเจจ เจœเจฟเจตเฉ‡เจ‚ เจ•เจฟ เจ‡เจนเจจเจพเจ‚ เจตเจฟเฉฑเจš เจšเจฐเจšเจพ เจ•เฉ€เจคเฉ€ เจ—เจˆ เจนเฉˆ PostgreSQL เจเจ‚เจŸเฉ€เจชเฉˆเจŸเจฐเจจ: "เจฎเจฐเฉ‡" เจฆเฉ€ เจญเฉ€เฉœ เจจเจพเจฒ เจฒเฉœเจจเจพ.

เจชเจฐ เจคเฉเจนเจพเจจเฉ‚เฉฐ เจ‡เจน เจธเจฎเจเจฃ เจฆเฉ€ เจฒเฉ‹เฉœ เจนเฉˆ เจ•เจฟ เจตเฉˆเจ•เจฟเจŠเจฎ เจซเฉเจฒ เจตเฉ€ เจนเจฎเฉ‡เจธเจผเจพ เจฎเจฆเจฆ เจจเจนเฉ€เจ‚ เจ•เจฐ เจธเจ•เจฆเจพเฅค เจ…เจœเจฟเจนเฉ‡ เจฎเจพเจฎเจฒเจฟเจ†เจ‚ เจฒเจˆ, เจฒเฉ‡เจ– เจคเฉ‹เจ‚ เจเจฒเจ—เฉ‹เจฐเจฟเจฆเจฎ เจจเจพเจฒ เจ†เจชเจฃเฉ‡ เจ†เจช เจจเฉ‚เฉฐ เจœเจพเจฃเฉ‚ เจ•เจฐเจตเจพเจ‰เจฃเจพ เจฎเจนเฉฑเจคเจตเจชเฉ‚เจฐเจฃ เจนเฉˆ DBA: เจœเจฆเฉ‹เจ‚ เจตเฉˆเจ•เจฟเจŠเจฎ เจ…เจธเจซเจฒ เจนเฉ‹ เจœเจพเจ‚เจฆเจพ เจนเฉˆ, เจ…เจธเฉ€เจ‚ เจŸเฉ‡เจฌเจฒ เจจเฉ‚เฉฐ เจนเฉฑเจฅเฉ€เจ‚ เจธเจพเจซเจผ เจ•เจฐเจฆเฉ‡ เจนเจพเจ‚.

#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 เจธเจตเจพเจฒเจพเจ‚ เจฒเจˆ เจชเจ•เจตเจพเจจเจพเจ‚
[explanation.tensor.ru 'เจคเฉ‡ เจฆเฉ‡เจ–เฉ‹]

เจ‡เฉฐเจกเฉˆเจ•เจธ เจฆเฉ‡ เจ…เจจเฉเจธเจพเจฐ เจตเฉ€, เจธเจญ เจ•เฉเจ เจ เฉ€เจ• เจœเจพเจชเจฆเจพ เจนเฉˆ, เจชเจฐ เจ‡เจน เจ•เจฟเจธเฉ‡ เจคเจฐเฉเจนเจพเจ‚ เจธเจผเฉฑเจ•เฉ€ เจนเฉˆ - เจชเฉœเฉเจนเฉ‡ เจ—เจ 20 เจฐเจฟเจ•เจพเจฐเจกเจพเจ‚ เจตเจฟเฉฑเจšเฉ‹เจ‚ เจนเจฐเฉ‡เจ• เจฒเจˆ, เจธเจพเจจเฉ‚เฉฐ 4 เจชเฉฐเจจเจฟเจ†เจ‚ เจฆเฉ‡ เจกเฉ‡เจŸเจพ, 32KB เจชเฉเจฐเจคเฉ€ เจฐเจฟเจ•เจพเจฐเจก เจ˜เจŸเจพเจ‰เจฃเจพ เจชเจฟเจ† - เจ•เฉ€ เจ‡เจน เจฌเฉ‹เจฒเจก เจจเจนเฉ€เจ‚ เจนเฉˆ? เจ…เจคเฉ‡ เจธเฉ‚เจšเจ•เจพเจ‚เจ• เจฆเจพ เจจเจพเจฎ tbl_fk_org_fk_cli_idx เจธเฉ‹เจš-เจ‰เจ•เจธเจพเจ‰เจฃ เจตเจพเจฒเจพเฅค

เจ เฉ€เจ• เจ•เจฐเจจเจพ:

CREATE INDEX ON tbl(fk_cli);

เจฌเฉ€เจฎเจพเจฐ SQL เจธเจตเจพเจฒเจพเจ‚ เจฒเจˆ เจชเจ•เจตเจพเจจเจพเจ‚
[explanation.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

เจฟเจธเจซเจผเจพเจฐ

เจœเฉ‡เจ•เจฐ เจ“เจชเจฐเฉ‡เจธเจผเจจ เจฆเฉเจ†เจฐเจพ เจตเจฐเจคเฉ€ เจ—เจˆ เจฎเฉˆเจฎเฉ‹เจฐเฉ€ เจฆเฉ€ เจฎเจพเจคเจฐเจพ เจชเฉˆเจฐเจพเจฎเฉ€เจŸเจฐ เจฆเฉ‡ เจจเจฟเจฐเจงเจพเจฐเจค เจฎเฉเฉฑเจฒ เจคเฉ‹เจ‚ เจฌเจนเฉเจค เจœเจผเจฟเจ†เจฆเจพ เจจเจนเฉ€เจ‚ เจนเฉˆ work_mem, เจ‡เจธ เจจเฉ‚เฉฐ เจ เฉ€เจ• เจ•เจฐเจจ เจฆเฉ€ เจ•เฉ€เจฎเจค เจนเฉˆ. เจคเฉเจธเฉ€เจ‚ เจคเฉเจฐเฉฐเจค เจนเจฐ เจ•เจฟเจธเฉ‡ เจฒเจˆ เจธเฉฐเจฐเจšเจจเจพ เจตเจฟเฉฑเจš เจ•เจฐ เจธเจ•เจฆเฉ‡ เจนเฉ‹, เจœเจพเจ‚ เจคเฉเจธเฉ€เจ‚ เจ•เจฐ เจธเจ•เจฆเฉ‡ เจนเฉ‹ SET [LOCAL] เจ•เจฟเจธเฉ‡ เจ–เจพเจธ เจฌเฉ‡เจจเจคเฉ€/เจฒเฉˆเจฃ-เจฆเฉ‡เจฃ เจฒเจˆเฅค

เจ‰เจฆเจพเจนเจฐเจจ:

SHOW work_mem;
-- "16MB"

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

เจฌเฉ€เจฎเจพเจฐ SQL เจธเจตเจพเจฒเจพเจ‚ เจฒเจˆ เจชเจ•เจตเจพเจจเจพเจ‚
[explanation.tensor.ru 'เจคเฉ‡ เจฆเฉ‡เจ–เฉ‹]

เจ เฉ€เจ• เจ•เจฐเจจเจพ:

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

เจฌเฉ€เจฎเจพเจฐ SQL เจธเจตเจพเจฒเจพเจ‚ เจฒเจˆ เจชเจ•เจตเจพเจจเจพเจ‚
[explanation.tensor.ru 'เจคเฉ‡ เจฆเฉ‡เจ–เฉ‹]

เจธเจชเฉฑเจธเจผเจŸ เจ•เจพเจฐเจจเจพเจ‚ เจ•เจฐเจ•เฉ‡, เจœเฉ‡เจ•เจฐ เจธเจฟเจฐเจซเจผ เจฎเฉˆเจฎเฉ‹เจฐเฉ€ เจตเจฐเจคเฉ€ เจœเจพเจ‚เจฆเฉ€ เจนเฉˆ เจ…เจคเฉ‡ เจกเจฟเจธเจ• เจจเจนเฉ€เจ‚, เจคเจพเจ‚ เจชเฉเฉฑเจ›เจ—เจฟเฉฑเจ› เจฌเจนเฉเจค เจคเฉ‡เจœเจผเฉ€ เจจเจพเจฒ เจšเจฒเจพเจˆ เจœเจพเจตเฉ‡เจ—เฉ€เฅค เจ‰เจธเฉ‡ เจธเจฎเฉ‡เจ‚, HDD เจคเฉ‹เจ‚ เจฒเฉ‹เจก เจฆเจพ เจนเจฟเฉฑเจธเจพ เจตเฉ€ เจนเจŸเจพ เจฆเจฟเฉฑเจคเจพ เจœเจพเจ‚เจฆเจพ เจนเฉˆ.

เจชเจฐ เจคเฉเจนเจพเจจเฉ‚เฉฐ เจ‡เจน เจธเจฎเจเจฃ เจฆเฉ€ เจœเจผเจฐเฉ‚เจฐเจค เจนเฉˆ เจ•เจฟ เจคเฉเจธเฉ€เจ‚ เจนเจฎเฉ‡เจธเจผเจพเจ‚ เจฌเจนเฉเจค เจธเจพเจฐเฉ€ เจ…เจคเฉ‡ เจฌเจนเฉเจค เจธเจพเจฐเฉ€ เจฎเฉˆเจฎเฉ‹เจฐเฉ€ เจจเจฟเจฐเจงเจพเจฐเจค เจ•เจฐเจจ เจฆเฉ‡ เจฏเฉ‹เจ— เจจเจนเฉ€เจ‚ เจนเฉ‹เจตเฉ‹เจ—เฉ‡ - เจ‡เฉฑเจฅเฉ‡ เจนเจฐ เจ•เจฟเจธเฉ‡ เจฒเจˆ เจ•เจพเจซเจผเฉ€ เจจเจนเฉ€เจ‚ เจนเฉ‹เจตเฉ‡เจ—เจพเฅค

#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

เจ‡เฉฑเจ• เจŸเจฟเฉฑเจชเจฃเฉ€ เจœเฉ‹เฉœเฉ‹