ืจืขืกื™ืคึผืขืก ืคึฟืึทืจ ืงืจืึทื ืง ืกืงืœ ืงื•ื•ื™ืจื™ื–

ืขื˜ืœืขื›ืข ื—ื“ืฉื™ื ืฆื•ืจื™ืง ืžื™ืจ ืžื•ื“ื™ืข explain.tensor.ru - ืขืคื ื˜ืœืขืš ืกืขืจื•ื•ื™ืก ืคึฟืึทืจ ืคึผืึทืจืกื™ื ื’ ืื•ืŸ ื•ื•ื™ื–ืฉื•ื•ืึทืœื™ื™ื–ื™ื ื’ ืึธื ืคึฟืจืขื’ ืคึผืœืึทื ื– ืฆื• PostgreSQL.

ืื™ืจ'ื•ื•ืข ื’ืขื•ื•ื™ื™ื ื˜ ืขืก ืื™ื‘ืขืจ 6000 ืžืืœ ื–ื™ื ื˜ ื“ืขืžืึธืœื˜, ืึธื‘ืขืจ ืื™ื™ื ืขืจ ืคื•ืŸ ื“ื™ ื”ืึทื ื˜ื™ืง ืคึฟืขื™ึดืงื™ื™ื˜ืŸ ืงืขืŸ ื”ืึธื‘ืŸ ื ื™ื˜ืึธ ืึทื ื ืึธื•ื˜ื™ืกื˜ ืื™ื– ืกื˜ืจืึทืงื˜ืฉืขืจืึทืœ ืงืœื•ื–, ื•ื•ืึธืก ืงื•ืง ืขืคึผืขืก ื•ื•ื™ ื“ืึธืก:

ืจืขืกื™ืคึผืขืก ืคึฟืึทืจ ืงืจืึทื ืง ืกืงืœ ืงื•ื•ื™ืจื™ื–

ื”ืขืจืŸ ืฆื• ื–ื™ื™ ืื•ืŸ ื“ื™ื™ืŸ ืจื™ืงื•ื•ืขืก ื•ื•ืขื˜ "ื•ื•ืขืจืŸ ืกื™ืœืงื™ ื’ืœืึทื˜". ๐Ÿ™‚

ืึธื‘ืขืจ ืขืžืขืก, ืคื™ืœืข ืกื™ื˜ื•ืึทื˜ื™ืึธื ืก ื•ื•ืึธืก ืžืึทื›ืŸ ืึท ื‘ืงืฉื” ืคึผืึทืžืขืœืขืš ืื•ืŸ "ื’ืœืึทื˜ืึทื ืึทืก" ืื™ืŸ ื˜ืขืจืžื™ื ืขืŸ ืคื•ืŸ ืจืขืกื•ืจืกืŸ, ื–ืขื ืขืŸ ื˜ื™ืคึผื™ืฉ ืื•ืŸ ืงืขื ืขืŸ ื–ื™ื™ืŸ ืื ืขืจืงืขื ื˜ ื“ื•ืจืš ื“ื™ ืกื˜ืจื•ืงื˜ื•ืจ ืื•ืŸ ื“ืึทื˜ืŸ ืคื•ืŸ ื“ืขื ืคึผืœืึทืŸ.

ืื™ืŸ ื“ืขื ืคืึทืœ, ื™ืขื“ืขืจ ื™ื—ื™ื“ ื“ืขื•ื•ืขืœืึธืคึผืขืจ ื•ื•ืขื˜ ื ื™ืฉื˜ ื”ืึธื‘ืŸ ืฆื• ืงื•ืงืŸ ืคึฟืึทืจ ืึทืŸ ืึทืคึผื˜ืึทืžืึทื–ื™ื™ืฉืึทืŸ ืึธืคึผืฆื™ืข ืื•ื™ืฃ ื–ื™ื™ืŸ ืื™ื™ื’ืŸ, ืจื™ืœื™ื™ื™ื ื’ ื‘ืœื•ื™ื– ืื•ื™ืฃ ื–ื™ื™ืŸ ืื™ื™ื’ืขื ืข ื“ืขืจืคืึทืจื•ื ื’ - ืžื™ืจ ืงืขื ืขืŸ ื–ืึธื’ืŸ ืื™ื ื•ื•ืึธืก ืื™ื– ื’ืขืฉืขืขื ื™ืฉ ื“ืึธ, ื•ื•ืึธืก ืงืขืŸ ื–ื™ื™ืŸ ื“ื™ ืกื™ื‘ื”, ืื•ืŸ ื•ื•ื™ ืฆื• ืงื•ืžืขืŸ ืึทืจื•ื™ืฃ ืžื™ื˜ ืึท ืœื™ื™ื–ื•ื ื’. ื•ื•ืึธืก ืื™ื– ื•ื•ืึธืก ืžื™ืจ ื”ืึธื‘ืŸ ื’ืขื˜ืืŸ.

ืจืขืกื™ืคึผืขืก ืคึฟืึทืจ ืงืจืึทื ืง ืกืงืœ ืงื•ื•ื™ืจื™ื–

ื–ืืœ ืก ื ืขืžืขืŸ ืึท ื ืขืขื ื˜ืขืจ ืงื•ืง ืื™ืŸ ื“ื™ ืงืึทืกืขืก - ื•ื•ื™ ื–ื™ื™ ื–ืขื ืขืŸ ื“ื™ืคื™ื™ื ื“ ืื•ืŸ ื•ื•ืึธืก ืจืขืงืึทืžืึทื ื“ื™ื™ืฉืึทื ื– ื–ื™ื™ ืคื™ืจืŸ ืฆื•.

ืคึฟืึทืจ ืึท ื‘ืขืกืขืจ ื˜ื‘ื™ืœื” ืื™ืŸ ื“ืขืจ ื˜ืขืžืข, ืื™ืจ ืงืขื ืขืŸ ืขืจืฉื˜ืขืจ ื”ืขืจืŸ ืฆื• ื“ื™ ืงืึธืจืึทืกืคึผืึทื ื“ื™ื ื’ ื‘ืœืึธืง ืคึฟื•ืŸ ืžื™ื™ืŸ ื‘ืึทืจื™ื›ื˜ ื‘ื™ื™ 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;

ืจืขืกื™ืคึผืขืก ืคึฟืึทืจ ืงืจืึทื ืง ืกืงืœ ืงื•ื•ื™ืจื™ื–
[ืงื•ืง ืื•ื™ืฃ explain.tensor.ru]

ืื™ืจ ืงืขื ืขืŸ ืžื™ื“ ื‘ืึทืžืขืจืงืŸ ืึทื– ืžืขืจ ื•ื•ื™ 100 ืจืขืงืึธืจื“ืก ื–ืขื ืขืŸ ืกืึทื‘ื˜ืจืึทืงื˜ื™ื“ ื“ื•ืจืš ื“ื™ ืื™ื ื“ืขืงืก, ื•ื•ืึธืก ื–ืขื ืขืŸ ื“ืขืžืึธืœื˜ ืึทืœืข ืื•ื™ืกื’ืขืฉื˜ืขืœื˜, ืื•ืŸ ื“ืขืจ ื‘ืœื•ื™ื– ืื™ื™ื ืขืจ ืื™ื– ืœื™ื ืงืก.

ืžื™ืจ ืคืึทืจืจื™ื›ื˜ืŸ:

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

ืจืขืกื™ืคึผืขืก ืคึฟืึทืจ ืงืจืึทื ืง ืกืงืœ ืงื•ื•ื™ืจื™ื–
[ืงื•ืง ืื•ื™ืฃ explain.tensor.ru]

ืืคื™ืœื• ืื•ื™ืฃ ืึทื–ืึท ืคึผืจื™ืžื™ื˜ื™ื•ื• ืžื•ืกื˜ืขืจ - 8.5 ืงืก ืคืึทืกื˜ืขืจ ืื•ืŸ 33 ืงืก ื•ื•ื™ื™ื ื™ืงืขืจืข ืœื™ื™ืขื ืขืŸ. ื“ื™ ื•ื•ื™ืจืงื•ื ื’ ื•ื•ืขื˜ ื–ื™ื™ืŸ ืงืœื™ืจืขืจ, ื“ื™ ืžืขืจ "ืคืืงื˜ืŸ" ืื™ืจ ื”ืึธื‘ืŸ ืคึฟืึทืจ ื™ืขื“ืขืจ ื•ื•ืขืจื˜. fk.

ืื™ืš ื˜ืึธืŸ ืึทื– ืึทื–ืึท ืึทืŸ ืื™ื ื“ืขืงืก ื•ื•ืขื˜ ืึทืจื‘ืขื˜ืŸ ื•ื•ื™ ืึท "ืคึผืจืขืคื™ืงืก" ืื™ื ื“ืขืงืก ื ื™ื˜ ืขืจื’ืขืจ ื•ื•ื™ ื“ื™ ืคืจื™ืขืจื“ื™ืงืข ืคึฟืึทืจ ืื ื“ืขืจืข ืงื•ื•ื™ืจื™ื– ืžื™ื˜ fk, ื•ื•ื• ืกืึธืจื˜ื™ื ื’ ื“ื•ืจืš pk ืื™ื– ื ื™ืฉื˜ ืื•ืŸ ืื™ื– ื ื™ืฉื˜ (ืื™ืจ ืงืขื ื˜ ืœื™ื™ืขื ืขืŸ ืžืขืจ ื•ื•ืขื’ืŸ ื“ืขื ืื™ืŸ ืžื™ื™ืŸ ืึทืจื˜ื™ืงืœ ื•ื•ืขื’ืŸ ื“ืขืจื’ื™ื™ื•ื ื’ ื‘ืึทื˜ืœืึธื ื™ืฉ ื™ื ื“ืขืงืกื™ื–). ืื™ืŸ ื‘ืึทื–ื•ื ื“ืขืจ, ืขืก ื•ื•ืขื˜ ืฆื•ืฉื˜ืขืœืŸ ื ืึธืจืžืึทืœ ื™ืงืกืคึผืœื™ืกืึทื˜ ืคืจืขืžื“ ืฉืœื™ืกืœ ืฉื˜ื™ืฆืŸ ื“ื•ืจืš ื“ืขื ืคืขืœื“.

#2: ืื™ื ื“ืขืงืก ื™ื ื˜ืขืจืกืขืงืฉืึทืŸ (ื‘ื™ื˜ืžืึทืคึผืึทื ื“)

ื•ื•ืขืŸ ื˜ื•ื˜

ื•ื•ื™ื™ึทื–ืŸ ืึทืœืข ืงืึทื ื˜ืจืึทืงืฅ ืคึฟืึทืจ ื“ืขื ืงืœื™ืขื ื˜ "ืœืœืง ืงืึธืœืึธืงืึธืœื˜ืฉื™ืง" ื’ืขืคื•ื ืขืŸ ืื•ื™ืฃ ื‘ื™ื›ืึทืฃ ืคื•ืŸ "ื ื“ื–ืฉืกืง ืœื™ื•ื˜ื™ืง".

ื•ื•ื™ ืฆื• ื™ื“ืขื ื˜ื™ืคื™ืฆื™ืจืŸ

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

ืจืขืกื™ืคึผืขืก ืคึฟืึทืจ ืงืจืึทื ืง ืกืงืœ ืงื•ื•ื™ืจื™ื–
[ืงื•ืง ืื•ื™ืฃ explain.tensor.ru]

ืžื™ืจ ืคืึทืจืจื™ื›ื˜ืŸ:

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

ืจืขืกื™ืคึผืขืก ืคึฟืึทืจ ืงืจืึทื ืง ืกืงืœ ืงื•ื•ื™ืจื™ื–
[ืงื•ืง ืื•ื™ืฃ explain.tensor.ru]

ื“ืึธ ื“ื™ ื’ืขื•ื•ื™ื ืก ืื™ื– ืงืœืขื ืขืจืขืจ, โ€‹โ€‹โ€‹โ€‹ื•ื•ื™ื™ึทืœ ื‘ื™ื˜ืžืึทืคึผ ื”ืขืึทืคึผ ืกืงืึทืŸ ืื™ื– ื’ืึทื ืฅ ืขืคืขืงื˜ื™ื•ื• ืื•ื™ืฃ ื–ื™ืš. ืื‘ืขืจ ืกื™ื™ึท ื•ื•ื™ ืกื™ื™ึท 7 ืงืก ืคืึทืกื˜ืขืจ ืื•ืŸ 2.5 ืงืก ื•ื•ื™ื™ื ื™ืงืขืจืข ืœื™ื™ืขื ืขืŸ.

#3: ืงืึทืžื‘ื™ื™ื ื™ื ื’ ื™ื ื“ืขืงืกื™ื– (ื‘ื™ื˜ืžืึทืคึผืึธืจ)

ื•ื•ืขืŸ ื˜ื•ื˜

ื•ื•ื™ื™ึทื–ืŸ ื“ื™ ืขืจืฉื˜ืขืจ 20 ืึธื•ืœื“ืึทืกื˜ "ืื™ื™ื’ืŸ" ืึธื“ืขืจ ืึทื ืกืึทืกื™ื™ื ื“ ืจื™ืงื•ื•ืขืก ืคึฟืึทืจ ืคึผืจืึทืกืขืกื™ื ื’, ืžื™ื˜ ืื™ื™ื’ืขื ืข ืื™ืŸ ื‘ื™ืœื›ืขืจืงื™ื™ึทื˜.

ื•ื•ื™ ืฆื• ื™ื“ืขื ื˜ื™ืคื™ืฆื™ืจืŸ

-> BitmapOr
   -> Bitmap Index Scan
   -> Bitmap Index Scan

ืจืขืงืึทืžืึทื ื“ื™ื™ืฉืึทื ื–

ื ื™ืฅ ื™ื•ื ื™ืึทืŸ [ืึทืœืข] ืฆื• ืคืึทืจื‘ื™ื ื“ืŸ ืกื•ื‘ืงื•ื•ืขืจื™ื– ืคึฟืึทืจ ื™ืขื“ืขืจ ืคื•ืŸ ื“ื™ ืฆื•ืฉื˜ืึทื ื“ ืึธื“ืขืจ ื‘ืœืึทืงืก.

ื‘ื™ื™ึทืฉืคึผื™ืœ:

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;

ืจืขืกื™ืคึผืขืก ืคึฟืึทืจ ืงืจืึทื ืง ืกืงืœ ืงื•ื•ื™ืจื™ื–
[ืงื•ืง ืื•ื™ืฃ explain.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, ะฑะพะปัŒัˆะต ะธ ะฝะต ะฝะฐะดะพ

ืจืขืกื™ืคึผืขืก ืคึฟืึทืจ ืงืจืึทื ืง ืกืงืœ ืงื•ื•ื™ืจื™ื–
[ืงื•ืง ืื•ื™ืฃ explain.tensor.ru]

ืžื™ืจ ื”ืึธื‘ืŸ ื’ืขื ื•ืฆื˜ ื“ื™ ืคืึทืงื˜ ืึทื– ืึทืœืข 20 ื ื™ื™ื˜ื™ืง ืจืขืงืึธืจื“ืก ื–ืขื ืขืŸ ื’ืœื™ื™ืš ื‘ืืงื•ืžืขืŸ ืื™ืŸ ื“ืขืจ ืขืจืฉื˜ืขืจ ื‘ืœืึธืง, ืึทื–ื•ื™ ื“ื™ ืฆื•ื•ื™ื™ื˜ืข, ืžื™ื˜ ื“ื™ ืžืขืจ "ื˜ื™ื™ึทืขืจ" ื‘ื™ื˜ืžืึทืคึผ ื”ืขืึทืคึผ ืกืงืึทืŸ, ืื™ื– ื ื™ืฉื˜ ืืคื™ืœื• ืขืงืกืึทืงื™ื•ื˜ืึทื“ - ื•ื•ื™ ืึท ืจืขื–ื•ืœื˜ืึทื˜ 22 ืงืก ืคืึทืกื˜ืขืจ, 44 ืงืก ื•ื•ื™ื™ื ื™ืงืขืจืข ืœื™ื™ืขื ืขืŸ!

ื ืžืขืจ ื“ื™ื˜ื™ื™ืœื“ ื“ืขืจืฆื™ื™ืœื•ื ื’ ื•ื•ืขื’ืŸ ื“ืขื ืึทืคึผื˜ืึทืžืึทื–ื™ื™ืฉืึทืŸ ืื•ืคึฟืŸ ืื•ื™ืฃ ืงืึธื ืงืจืขื˜ืข ื‘ื™ื™ืฉืคื™ืœืŸ ืงืขื ืขืŸ ื–ื™ื™ืŸ ืœื™ื™ืขื ืขืŸ ืื™ืŸ ืึทืจื˜ื™ืงืœืขืŸ PostgreSQL ืึทื ื˜ื™ืคึผืึทื˜ื˜ืขืจื ืก: ืฉืขื“ืœืขืš ื“ื–ืฉื•ื™ื ืฅ ืื•ืŸ ืึธืจืก ะธ PostgreSQL Antipatterns: ืึท ื“ืขืจืฆื™ื™ืœื•ื ื’ ืคื•ืŸ ื™ื˜ืขืจืึทื˜ื™ื•ื• ืจืึทืคื™ื ื™ืจื˜ืงื™ื™ึทื˜ ืคื•ืŸ ื–ื•ื›ืŸ ื“ื•ืจืš ื ืึธืžืขืŸ, ืึธื“ืขืจ "ืึธืคึผื˜ื™ืžื™ื–ื™ื ื’ ืฆื•ืจื™ืง ืื•ืŸ ืึทืจื•ื™ืก".

ื’ืขื ืขืจืึทืœื™ื–ืขื“ ื•ื•ืขืจืกื™ืข ื‘ืืคื•ื™ืœืŸ ืกืขืœืขืงืฆื™ืข ื“ื•ืจืš ืขื˜ืœืขื›ืข ืฉืœื™ืกืœืขืŸ (ืื•ืŸ ื ื™ื˜ ื ืึธืจ ืคึฟืึทืจ ื“ื™ ืงืึธื ืกื˜ / ื ื•ืœ ืคึผืึธืจ) ืื™ื– ื“ื™ืกืงืึทืกื˜ ืื™ืŸ ื“ืขื ืึทืจื˜ื™ืงืœ SQL HowTo: ืฉืจื™ื™ึทื‘ืŸ ืึท ื‘ืฉืขืช-ืฉืœื™ื™ืฃ ื’ืœื™ื™ึทืš ืื™ืŸ ื“ื™ ืึธื ืคึฟืจืขื’, ืึธื“ืขืจ "ืขืœืขืžืขื ื˜ืึทืจื™ ื“ืจื™ื™-ื•ื•ืขื’".

#4: ืžื™ืจ ืœื™ื™ืขื ืขืŸ ืฆื• ืคื™ืœ

ื•ื•ืขืŸ ื˜ื•ื˜

ื•ื•ื™ ืึท ื”ืขืจืฉืŸ, ืขืก ืึทืงืขืจื– ื•ื•ืขืŸ ืื™ืจ ื•ื•ื™ืœืŸ ืฆื• "ืฆื•ื˜ืฉืขืคึผืขืŸ ืืŸ ืื ื“ืขืจ ืคื™ืœื˜ืขืจ" ืฆื• ืึท ื™ื’ื–ื™ืกื˜ื™ื ื’ ื‘ืงืฉื”.

"ืื•ืŸ ืื™ืจ ื˜ืึธืŸ ื ื™ื˜ ื”ืึธื‘ืŸ ื“ื™ ื–ืขืœื‘ืข, ืึธื‘ืขืจ ืžื™ื˜ ืคึผืขืจืœ ืงื ืขืคึผืœืขืš? ยป ืคื™ืœื "ื“ื™ืึทืžืึธื ื“ ื”ืึทื ื˜"

ืคึฟืึทืจ ื‘ื™ื™ึทืฉืคึผื™ืœ, ืžืึธื“ื™ืคื™ืฆื™ืจืŸ ื“ื™ ืึทืจื‘ืขื˜ ืื•ื™ื‘ืŸ, ื•ื•ื™ื™ึทื–ืŸ ื“ื™ ืขืจืฉื˜ืขืจ 20 ืึธื•ืœื“ืึทืกื˜ "ืงืจื™ื˜ื™ืฉ" ืจื™ืงื•ื•ืขืก ืคึฟืึทืจ ืคึผืจืึทืกืขืกื™ื ื’, ืจืึทื’ืึทืจื“ืœืึทืก ืคื•ืŸ ื–ื™ื™ืขืจ ืฆื™ืœ.

ื•ื•ื™ ืฆื• ื™ื“ืขื ื˜ื™ืคื™ืฆื™ืจืŸ

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

ืจืขืงืึทืžืึทื ื“ื™ื™ืฉืึทื ื–

ืฉืึทืคึฟืŸ [ืžืขืจ] ืกืคึผืขืฉืึทืœื™ื™ื–ื“ ืื™ื ื“ืขืงืก ืžื™ื˜ WHERE ืคึผื•ื ืงื˜ ืึธื“ืขืจ ืึทืจื™ื™ึทื ื ืขืžืขืŸ ื ืึธืš ืคืขืœื“ืขืจ ืื™ืŸ ื“ื™ ืื™ื ื“ืขืงืก.

ืื•ื™ื‘ ื“ื™ ืคึฟื™ืœื˜ืจื™ืจื•ื ื’ ืฆื•ืฉื˜ืึทื ื“ ืื™ื– "ืกื˜ืึทื˜ื™ืง" ืคึฟืึทืจ ื“ื™ื™ืŸ ื˜ืึทืกืงืก - ื“ืึธืก ืื™ื– ื˜ื•ื˜ ื ื™ืฉื˜ ืึทืจื™ื™ึทื ื ืขืžืขืŸ ื™ืงืกืคึผืึทื ืฉืึทืŸ ืจืฉื™ืžื” ืคื•ืŸ ื•ื•ืึทืœื•ืขืก ืื™ืŸ ื“ืขืจ ืฆื•ืงื•ื ืคึฟื˜ - ืขืก ืื™ื– ื‘ืขืกืขืจ ืฆื• ื ื•ืฆืŸ ืึท WHERE ืื™ื ื“ืขืงืก. ืคืึทืจืฉื™ื“ืŸ ื‘ื•ืœื™ืึทืŸ / ืขื ื•ื ืกื˜ืึทื˜ื•ืกืขืก ืคึผืึทืกื™ืง ื’ืขื–ื•ื ื˜ ืื™ืŸ ื“ืขื ืงืึทื˜ืขื’ืึธืจื™ืข.

ืื•ื™ื‘ ื“ื™ Filtration ืฆื•ืฉื˜ืึทื ื“ ืงืขื ืขืŸ ื ืขืžืขืŸ ืื•ื™ืฃ ืคืึทืจืฉื™ื“ืขื ืข ื•ื•ืึทืœื•ืขืก, ืขืก ืื™ื– ื‘ืขืกืขืจ ืฆื• ื™ืงืกืคึผืึทื ื“ ื“ื™ ืื™ื ื“ืขืงืก ืžื™ื˜ ื“ื™ ืคืขืœื“ืขืจ - ื•ื•ื™ ืื™ืŸ ื“ื™ ืกื™ื˜ื•ืึทืฆื™ืข ืžื™ื˜ BitmapAnd ืื•ื™ื‘ืŸ.

ื‘ื™ื™ึทืฉืคึผื™ืœ:

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;

ืจืขืกื™ืคึผืขืก ืคึฟืึทืจ ืงืจืึทื ืง ืกืงืœ ืงื•ื•ื™ืจื™ื–
[ืงื•ืง ืื•ื™ืฃ explain.tensor.ru]

ืžื™ืจ ืคืึทืจืจื™ื›ื˜ืŸ:

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

ืจืขืกื™ืคึผืขืก ืคึฟืึทืจ ืงืจืึทื ืง ืกืงืœ ืงื•ื•ื™ืจื™ื–
[ืงื•ืง ืื•ื™ืฃ explain.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 Antipatterns: ืคื™ื™ื˜ื™ื ื’ ื”ืึธืจื“ืขืก ืคื•ืŸ "ื˜ื•ื™ื˜".

ืึธื‘ืขืจ ืžื™ืจ ืžื•ื–ืŸ ืคึฟืึทืจืฉื˜ื™ื™ืŸ ืึทื– ืืคื™ืœื• ื•ื•ืึทืงื•ื•ื ืคื•ืœ ืงืขื ืขืŸ ื ื™ืฉื˜ ืฉื˜ืขื ื“ื™ืง ื”ืขืœืคืŸ. ืคึฟืึทืจ ืึทื–ืึท ืงืึทืกืขืก, ืื™ืจ ื–ืึธืœ ื‘ืืงืขื ืขืŸ ื–ื™ืš ืžื™ื˜ ื“ื™ ืึทืœื’ืขืจื™ื“ืึทื ืคื•ืŸ ื“ืขื ืึทืจื˜ื™ืงืœ. ื“ื‘ืึท: ื•ื•ืขืŸ ื•ื•ืึทืงื•ื•ื ืคึผืึทืกื™ื–, โ€‹โ€‹ืžื™ืจ ืจื™ื™ืŸ ื“ื™ ื˜ื™ืฉ ืžืึทื ื™ื•ืึทืœื™.

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

ืจืขืกื™ืคึผืขืก ืคึฟืึทืจ ืงืจืึทื ืง ืกืงืœ ืงื•ื•ื™ืจื™ื–
[ืงื•ืง ืื•ื™ืฃ explain.tensor.ru]

ืึทืœืฅ ืžื™ื™ื ื˜ ืฆื• ื–ื™ื™ืŸ ืคื™ื™ึทืŸ, ืืคื™ืœื• ืื™ืŸ ื˜ืขืจืžื™ื ืขืŸ ืคื•ืŸ ื“ื™ ืื™ื ื“ืขืงืก, ืึธื‘ืขืจ ืขืคืขืก ืกืึทืกืคึผื™ืฉืึทืก - ืคึฟืึทืจ ื™ืขื“ืขืจ ืคื•ืŸ ื“ื™ 20 ืจืขืงืึธืจื“ืก ืœื™ื™ืขื ืขืŸ, 4 ื‘ืœืขื˜ืขืจ ืคื•ืŸ ื“ืึทื˜ืŸ ื”ืึธื‘ืŸ ืฆื• ื–ื™ื™ืŸ ืกืึทื‘ื˜ืจืึทืงื˜ื™ื“, 32KB ืคึผืขืจ ืจืขืงืึธืจื“ - ืื™ื– ืขืก ื ื™ืฉื˜ ื“ืจื™ื™ืกื˜? ื™ื ืื•ืŸ ืื™ื ื“ืขืงืก ื ืึธืžืขืŸ tbl_fk_org_fk_cli_idx ืคื™ืจื˜ ืฆื• ื’ืขื“ืึทื ืง.

ืžื™ืจ ืคืึทืจืจื™ื›ื˜ืŸ:

CREATE INDEX ON tbl(fk_cli);

ืจืขืกื™ืคึผืขืก ืคึฟืึทืจ ืงืจืึทื ืง ืกืงืœ ืงื•ื•ื™ืจื™ื–
[ืงื•ืง ืื•ื™ืฃ explain.tensor.ru]

ืคึผืœื•ืฆืœื™ื ื’ - 10 ืžืืœ ืคืึทืกื˜ืขืจ ืื•ืŸ 4 ืžืืœ ื•ื•ื™ื™ื ื™ืงืขืจ ืฆื• ืœื™ื™ืขื ืขืŸ!

ืคึฟืึทืจ ืžืขืจ ื‘ื™ื™ืฉืคื™ืœืŸ ืคื•ืŸ ื‘ืึทื˜ืœืึธื ื™ืฉ ื ื•ืฆืŸ ืคื•ืŸ ื™ื ื“ืขืงืกื™ื–, ื–ืขืŸ ื“ืขื ืึทืจื˜ื™ืงืœ ื“ื‘ืึท: ื’ืขืคึฟื™ื ืขืŸ ืึทืจื•ื™ืกื’ืขื•ื•ืึธืจืคืŸ ื™ื ื“ืขืงืกื™ื–.

#7: CTE ร— CTE

ื•ื•ืขืŸ ื˜ื•ื˜

ืื™ืŸ ื‘ืงืฉื” ืกืงืึธืจื“ "ืคืขื˜" CTE ืคื•ืŸ ืคืึทืจืฉื™ื“ืขื ืข ื˜ื™ืฉืŸ, ืื•ืŸ ื“ืขืžืึธืœื˜ ื‘ืึทืฉืœืึธืกืŸ ืฆื• ื˜ืึธืŸ ืฆื•ื•ื™ืฉืŸ ื–ื™ื™ JOIN.

ื“ืขืจ ืคืึทืœ ืื™ื– ื‘ืึทื˜ื™ื™ึทื˜ื™ืง ืคึฟืึทืจ ื•ื•ืขืจืกื™ืขืก ืื•ื ื˜ืขืจ ื•ื•12 ืึธื“ืขืจ ืจื™ืงื•ื•ืขืก ืžื™ื˜ WITH MATERIALIZED.

ื•ื•ื™ ืฆื• ื™ื“ืขื ื˜ื™ืคื™ืฆื™ืจืŸ

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

ืจืขืงืึทืžืึทื ื“ื™ื™ืฉืึทื ื–

ืึทื ืึทืœื™ื–ื™ืจืŸ ื“ื™ ื‘ืงืฉื” ืงืขืจืคืึทืœื™ ื–ืขื ืขืŸ CTEs ื“ืืจืฃ ื“ืึธ ืื™ืŸ ืึทืœืข? ืื•ื™ื‘ ื™ืึธ, ื“ืขืžืึธืœื˜ ืฆื•ืœื™ื™ื’ืŸ "ื•ื•ืขืจื˜ืขืจื‘ื•ืš" ืื™ืŸ hstore/json ืœื•ื™ื˜ ื“ื™ ืžืึธื“ืขืœ ื“ื™ืกืงืจื™ื™ื‘ื“ ืื™ืŸ PostgreSQL Antipatterns: ื•ื•ืขืจื˜ืขืจื‘ื•ืš ืฉืœืึธื’ืŸ ืฉื•ื•ืขืจ JOIN.

#8: ื•ื™ืกื‘ื™ื™ึทื˜ืŸ ืฆื• ื“ื™ืกืง (ื˜ืขืžืคึผ ื’ืขืฉืจื™ื‘ืŸ)

ื•ื•ืขืŸ ื˜ื•ื˜

ืื™ื™ืŸ ืžืึธืœ ืคึผืจืึทืกืขืกื™ื ื’ (ืกืึธืจื˜ื™ื ื’ ืึธื“ืขืจ ื™ื™ื ืฆื™ืง) ืคื•ืŸ ืึท ื’ืจื•ื™ืก ื ื•ืžืขืจ ืคื•ืŸ ืจืขืงืึธืจื“ืก ืื™ื– ื ื™ืฉื˜ ืคึผืึทืกื™ืง ืื™ืŸ ื“ื™ ื–ื™ืงืึธืจืŸ ืึทืœืึทืงื™ื™ื˜ื™ื“ ืคึฟืึทืจ ื“ืขื.

ื•ื•ื™ ืฆื• ื™ื“ืขื ื˜ื™ืคื™ืฆื™ืจืŸ

-> *
   && temp written > 0

ืจืขืงืึทืžืึทื ื“ื™ื™ืฉืึทื ื–

ืื•ื™ื‘ ื“ื™ ืกื•ืžืข ืคื•ืŸ โ€‹โ€‹โ€‹โ€‹ื–ื™ืงืึธืจืŸ ื’ืขื ื™ืฆื˜ ื“ื•ืจืš ื“ื™ ืึธืคึผืขืจืึทืฆื™ืข ื˜ื•ื˜ ื ื™ืฉื˜ ื™ืงืกื™ื“ ื“ื™ ื‘ืึทืฉื˜ื™ืžื˜ ื•ื•ืขืจื˜ ืคื•ืŸ ื“ื™ ืคึผืึทืจืึทืžืขื˜ืขืจ work_mem, ืขืก ื–ืึธืœ ื–ื™ื™ืŸ ืงืขืจืขืงื˜ืึทื“. ืื™ืจ ืงืขื ืขืŸ ื’ืœื™ื™ืš ืื™ืŸ ื“ื™ ืงืึทื ืคื™ื’ื™ืขืจื™ื™ืฉืึทืŸ ืคึฟืึทืจ ืึทืœืขืžืขืŸ, ืึธื“ืขืจ ืื™ืจ ืงืขื ืขืŸ ื“ื•ืจืš SET [LOCAL] ืคึฟืึทืจ ืึท ืกืคึผืขืฆื™ืคื™ืฉ ื‘ืงืฉื” / ื˜ืจืึทื ืกืึทืงื˜ื™ืึธืŸ.

ื‘ื™ื™ึทืฉืคึผื™ืœ:

SHOW work_mem;
-- "16MB"

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

ืจืขืกื™ืคึผืขืก ืคึฟืึทืจ ืงืจืึทื ืง ืกืงืœ ืงื•ื•ื™ืจื™ื–
[ืงื•ืง ืื•ื™ืฃ explain.tensor.ru]

ืžื™ืจ ืคืึทืจืจื™ื›ื˜ืŸ:

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

ืจืขืกื™ืคึผืขืก ืคึฟืึทืจ ืงืจืึทื ืง ืกืงืœ ืงื•ื•ื™ืจื™ื–
[ืงื•ืง ืื•ื™ืฃ explain.tensor.ru]

ืคึฟืึทืจ ืงืœืึธืจ ื•ื•ื™ ื“ืขืจ ื˜ืึธื’ ืกื™ื‘ื•ืช, ืื•ื™ื‘ ื‘ืœื•ื™ื– ื–ื›ึผืจื•ืŸ ืื™ื– ื’ืขื ื™ืฆื˜, ืื•ืŸ ื ื™ืฉื˜ ื“ื™ืกืง, ื“ื™ ืึธื ืคึฟืจืขื’ ื•ื•ืขื˜ ื–ื™ื™ืŸ ืขืงืกืึทืงื™ื•ื˜ืึทื“ ืคื™ืœ ืคืึทืกื˜ืขืจ. ืื™ืŸ ื“ืขืจ ื–ืขืœื‘ื™ืงืขืจ ืฆื™ื™ื˜, ื˜ื™ื™ืœ ืคื•ืŸ ื“ื™ ืžืึทืกืข ืื™ื– ืื•ื™ืš ืึทื•ื•ืขืงื’ืขื ื•ืžืขืŸ ืคื•ืŸ ื“ื™ ื”ื“ื“.

ืึธื‘ืขืจ ืื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ืคึฟืึทืจืฉื˜ื™ื™ืŸ ืึทื– ื“ื™ ืึทืœืึทืงื™ื™ืฉืึทืŸ ืคื•ืŸ ืึท ืคึผืœืึทืฅ ืคื•ืŸ ื–ื›ึผืจื•ืŸ ื•ื•ืขื˜ ืฉื˜ืขื ื“ื™ืง ื ื™ืฉื˜ ืึทืจื‘ืขื˜ืŸ - ืขืก ืื™ื– ืคืฉื•ื˜ ื ื™ืฉื˜ ื’ืขื ื•ื’ ืคึฟืึทืจ ืึทืœืขืžืขืŸ.

#9: ื™ืจืขืœืึทื•ื•ืึทื ื˜ ืกื˜ืึทื˜ื™ืกื˜ื™ืง

ื•ื•ืขืŸ ื˜ื•ื˜

ืืกืืš ื”ืื˜ ืžืขืŸ ื’ืœืฒืš ืืจืฒื ื’ืขื’ืืกืŸ ืื™ืŸ ื“ืขืจ ื‘ืื–ืข, ืื‘ืขืจ ื–ืฒ ื”ืื‘ืŸ ื ื™ืฉื˜ ื’ืขื”ืื˜ ืงืฒืŸ ืฆืฒื˜ ืขืก ืืฐืขืง ืฆื• ืคืืจื˜ืจื™ื‘ืŸ ANALYZE.

ื•ื•ื™ ืฆื• ื™ื“ืขื ื˜ื™ืคื™ืฆื™ืจืŸ

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

ืจืขืงืึทืžืึทื ื“ื™ื™ืฉืึทื ื–

ืคืึทืจื‘ืจืขื ื’ืขืŸ ื“ื™ ื–ืขืœื‘ืข ANALYZE.

ื“ืขื ืกื™ื˜ื•ืึทืฆื™ืข ืื™ื– ื“ื™ืกืงืจื™ื™ื‘ื“ ืื™ืŸ ืžืขืจ ื“ืขื˜ืึทืœ ืื™ืŸ PostgreSQL Antipatterns: ืกื˜ืึทื˜ื™ืกื˜ื™ืง ื–ืขื ืขืŸ ื“ื™ ื”ื•ื™ืคึผื˜ ืคื•ืŸ ืึทืœืฅ.

#10: "ืขืคึผืขืก ืื™ื– ืคืึทืœืฉ"

ื•ื•ืขืŸ ื˜ื•ื˜

ืขืก ืื™ื– ื’ืขื•ื•ืขืŸ ืึท ืฉืœืึธืก ื•ื•ืืจื˜ืŸ ืคึฟืึทืจ ืึท ืงืึทืžืคึผื™ื˜ื™ื ื’ ื‘ืขื˜ืŸ, ืึธื“ืขืจ ืขืก ืื™ื– ื ื™ืฉื˜ ื’ืขื ื•ื’ ืงืคึผื• / ื›ื™ื™ืคึผืขืจื•ื•ื™ื™ื–ืขืจ ื™ื™ึทื–ื ื•ื•ืึทืจื’ ืจืขืกื•ืจืกืŸ.

ื•ื•ื™ ืฆื• ื™ื“ืขื ื˜ื™ืคื™ืฆื™ืจืŸ

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

ืจืขืงืึทืžืึทื ื“ื™ื™ืฉืึทื ื–

ื ื™ืฆืŸ ืึท ืคื•ื ื“ืจื•ื™ืกื ื“ื™ืง ืžืึธื ื™ื˜ืึธืจื™ื ื’ ืกื™ืกื˜ืขื ืกืขืจื•ื•ืขืจ ืคึฟืึทืจ ื‘ืœืึทืงื™ื ื’ ืึธื“ืขืจ ืึทื‘ื ืึธืจืžืึทืœ ืžื™ื˜ืœ ืงืึทื ืกืึทืžืฉืึทืŸ. ืžื™ืจ ื”ืึธื‘ืŸ ืฉื•ื™ืŸ ื’ืขืจืขื“ื˜ ื•ื•ืขื’ืŸ ืื•ื ื“ื–ืขืจ ื•ื•ืขืจืกื™ืข ืคื•ืŸ โ€‹โ€‹ืึธืจื’ืึทื ื™ื™ื–ื™ื ื’ ื“ืขื ืคึผืจืึธืฆืขืก ืคึฟืึทืจ ื”ื•ื ื“ืขืจื˜ืขืจ ืคื•ืŸ ืกืขืจื•ื•ืขืจืก. ื“ืึธ ะธ ื“ืึธ.

ืจืขืกื™ืคึผืขืก ืคึฟืึทืจ ืงืจืึทื ืง ืกืงืœ ืงื•ื•ื™ืจื™ื–
ืจืขืกื™ืคึผืขืก ืคึฟืึทืจ ืงืจืึทื ืง ืกืงืœ ืงื•ื•ื™ืจื™ื–

ืžืงื•ืจ: www.habr.com

ืœื™ื™ื’ืŸ ืึท ื‘ืึทืžืขืจืงื•ื ื’