PostgreSQL Antipatterns: ืกื™ืคื•ืจ ืขืœ ื—ื™ื“ื•ื“ ืื™ื˜ืจื˜ื™ื‘ื™ ืฉืœ ื—ื™ืคื•ืฉ ืœืคื™ ืฉื, ืื• "ืื•ืคื˜ื™ืžื™ื–ืฆื™ื” ืงื“ื™ืžื” ื•ืื—ื•ืจื”"

ืืœืคื™ ืžื ื”ืœื™ื ืžืžืฉืจื“ื™ ืžื›ื™ืจื•ืช ื‘ืจื—ื‘ื™ ื”ืืจืฅ ืžืชืขื“ื™ื ืžืขืจื›ืช ื”-CRM ืฉืœื ื• ืขืฉืจื•ืช ืืœืคื™ ืื ืฉื™ ืงืฉืจ ืžื“ื™ ื™ื•ื - ืขื•ื‘ื“ื•ืช ืฉืœ ืชืงืฉื•ืจืช ืขื ืœืงื•ื—ื•ืช ืคื•ื˜ื ืฆื™ืืœื™ื™ื ืื• ืงื™ื™ืžื™ื. ื•ืœืฉื ื›ืš, ืชื—ื™ืœื” ื™ืฉ ืœืžืฆื•ื ืœืงื•ื—, ื•ืจืฆื•ื™ ืžื”ืจ ืžืื•ื“. ื•ื–ื” ืงื•ืจื” ืœืจื•ื‘ ื‘ืฉื.

ืœื›ืŸ, ืื™ืŸ ื–ื” ืžืคืชื™ืข ืฉืฉื•ื‘ ื ื™ืชื•ื— ืฉืื™ืœืชื•ืช "ื›ื‘ื“ื•ืช" ื‘ืื—ื“ ืžืžืื’ืจื™ ื”ืžื™ื“ืข ื”ื˜ืขื•ื ื™ื ื‘ื™ื•ืชืจ - ืฉืœื ื• ื—ืฉื‘ื•ืŸ ืืจื’ื•ื ื™ ืฉืœ VLSI, ืžืฆืืชื™ "ื‘ืจืืฉ" ื‘ืงืฉื” ืœื—ื™ืคื•ืฉ "ืžื”ื™ืจ" ืœืคื™ ืฉื ืขื‘ื•ืจ ื›ืจื˜ื™ืกื™ ืืจื’ื•ืŸ.

ื™ืชืจื” ืžื›ืš, ื—ืงื™ืจื” ื ื•ืกืคืช ื”ืขืœืชื” ื“ื•ื’ืžื” ืžืขื ื™ื™ื ืช ืชื—ื™ืœื” ืื•ืคื˜ื™ืžื™ื–ืฆื™ื” ื•ืœืื—ืจ ืžื›ืŸ ื™ืจื™ื“ื” ื‘ื‘ื™ืฆื•ืขื™ื ื‘ืงืฉื” ืขื ื—ื™ื“ื•ื“ ืจืฆื™ืฃ ืฉืœื” ืขืœ ื™ื“ื™ ืžืกืคืจ ืฆื•ื•ืชื™ื, ืฉื›ืœ ืื—ื“ ืžื”ื ืคืขืœ ืืš ื•ืจืง ืžืชื•ืš ื”ื›ื•ื•ื ื•ืช ื”ื˜ื•ื‘ื•ืช ื‘ื™ื•ืชืจ.

0: ืžื” ื”ืžืฉืชืžืฉ ืจืฆื”?

PostgreSQL Antipatterns: ืกื™ืคื•ืจ ืขืœ ื—ื™ื“ื•ื“ ืื™ื˜ืจื˜ื™ื‘ื™ ืฉืœ ื—ื™ืคื•ืฉ ืœืคื™ ืฉื, ืื• "ืื•ืคื˜ื™ืžื™ื–ืฆื™ื” ืงื“ื™ืžื” ื•ืื—ื•ืจื”"[KDPV ืžื›ืืŸ]

ืœืžื” ืžืชื›ื•ื•ืŸ ืžืฉืชืžืฉ ื‘ื“ืจืš ื›ืœืœ ื›ืฉื”ื•ื ืžื“ื‘ืจ ืขืœ ื—ื™ืคื•ืฉ "ืžื”ื™ืจ" ืœืคื™ ืฉื? ื–ื” ื›ืžืขื˜ ืืฃ ืคืขื ืœื ืžืชื‘ืจืจ ื›ื—ื™ืคื•ืฉ "ื›ื ื”" ืฉืœ ืชืช ืžื—ืจื•ื–ืช ื›ืžื• ... LIKE '%ั€ะพะทะฐ%' - ื›ื™ ืื– ื”ืชื•ืฆืื” ื›ื•ืœืœืช ืœื ืจืง 'ะ ะพะทะฐะปะธั' ะธ 'ะœะฐะณะฐะทะธะฝ ะ ะพะทะฐ'ืื‘ืœ 'ะ“ั€ะพะทะฐ' ื•ืืคื™ืœื• 'ะ”ะพะผ ะ”ะตะดะฐ ะœะพั€ะพะทะฐ'.

ื”ืžืฉืชืžืฉ ืžื ื™ื— ื‘ืจืžื” ื”ื™ื•ืžื™ื•ืžื™ืช ืฉืืชื” ืชืกืคืง ืœื• ื—ืคืฉ ืœืคื™ ืชื—ื™ืœืช ื”ืžื™ืœื” ื‘ื›ื•ืชืจืช ื•ืœื”ืคื•ืš ืื•ืชื” ืœืจืœื•ื•ื ื˜ื™ืช ื™ื•ืชืจ ืžืชื—ื™ืœ ืขื ื ื›ื ืก. ื•ืืชื” ืชืขืฉื” ืืช ื–ื” ื›ืžืขื˜ ื‘ืื•ืคืŸ ืžื™ื™ื“ื™ - ืขื‘ื•ืจ ืงืœื˜ ื‘ื™ืŸ-ืœื™ื ื™ืืจื™.

1: ื”ื’ื‘ืœ ืืช ื”ืžืฉื™ืžื”

ื•ืขื•ื“ ื™ื•ืชืจ ืžื›ืš, ืื“ื ืœื ื™ื™ื›ื ืก ืกืคืฆื™ืคื™ืช 'ั€ะพะท ะผะฐะณะฐะท', ื›ืš ืฉืชืฆื˜ืจืš ืœื—ืคืฉ ื›ืœ ืžื™ืœื” ืœืคื™ ืงื™ื“ื•ืžืช. ืœื, ืœืžืฉืชืžืฉ ื”ืจื‘ื” ื™ื•ืชืจ ืงืœ ืœื”ื’ื™ื‘ ืœืจืžื– ืžื”ื™ืจ ืขื‘ื•ืจ ื”ืžื™ืœื” ื”ืื—ืจื•ื ื” ืžืืฉืจ "ืœืคืจื˜" ื‘ื›ื•ื•ื ื” ืืช ื”ืงื•ื“ืžื™ื - ืชืจืื” ืื™ืš ื›ืœ ืžื ื•ืข ื—ื™ืคื•ืฉ ืžื˜ืคืœ ื‘ื–ื”.

ื›ืœืœื™ ื ื›ื•ืŸ ื’ื™ื‘ื•ืฉ ื”ื“ืจื™ืฉื•ืช ืœื‘ืขื™ื” ื”ื•ื ื™ื•ืชืจ ืžืžื—ืฆื™ืช ื”ืคืชืจื•ืŸ. ืœืคืขืžื™ื ื ื™ืชื•ื— ืžืงืจื” ืฉื™ืžื•ืฉ ื–ื”ื™ืจ ื™ื›ื•ืœ ืœื”ืฉืคื™ืข ื‘ืื•ืคืŸ ืžืฉืžืขื•ืชื™ ืขืœ ื”ืชื•ืฆืื”.

ืžื” ืขื•ืฉื” ืžืคืชื— ืื‘ืกื˜ืจืงื˜ื™?

1.0: ืžื ื•ืข ื—ื™ืคื•ืฉ ื—ื™ืฆื•ื ื™

ื”ื•, ื”ื—ื™ืคื•ืฉ ืงืฉื”, ืื ื™ ืœื ืจื•ืฆื” ืœืขืฉื•ืช ื›ืœื•ื - ื‘ื•ืื• ื ื™ืชืŸ ืืช ื–ื” ืœ-devops! ืชืŸ ืœื”ื ืœืคืจื•ืก ืžื ื•ืข ื—ื™ืคื•ืฉ ื—ื™ืฆื•ื ื™ ืœืžืกื“ ื”ื ืชื•ื ื™ื: Sphinx, ElasticSearch,...

ืืคืฉืจื•ืช ืขื‘ื•ื“ื”, ืื ื›ื™ ืขืชื™ืจืช ืขื‘ื•ื“ื” ืžื‘ื—ื™ื ืช ืกื ื›ืจื•ืŸ ื•ืžื”ื™ืจื•ืช ืฉื™ื ื•ื™ื™ื. ืืš ืœื ื‘ืขื ื™ื™ื ื ื•, ืฉื›ืŸ ื”ื—ื™ืคื•ืฉ ืžืชื‘ืฆืข ืขื‘ื•ืจ ื›ืœ ืœืงื•ื— ืจืง ื‘ืžืกื’ืจืช ื ืชื•ื ื™ ื—ืฉื‘ื•ื ื•. ื•ืœื ืชื•ื ื™ื ื™ืฉ ืฉื•ื ื•ืช ื“ื™ ื’ื‘ื•ื”ื” - ื•ืื ื”ืžื ื”ืœ ื ื›ื ืก ืขื›ืฉื™ื• ืœื›ืจื˜ื™ืก 'ะœะฐะณะฐะทะธะฝ ะ ะพะทะฐ', ื•ืื– ืื—ืจื™ 5-10 ืฉื ื™ื•ืช ื”ื•ื ืื•ืœื™ ื›ื‘ืจ ื–ื•ื›ืจ ืฉื”ื•ื ืฉื›ื— ืœืฆื™ื™ืŸ ืฉื ืืช ื”ืžื™ื™ืœ ืฉืœื• ื•ืจื•ืฆื” ืœืžืฆื•ื ืื•ืชื• ื•ืœืชืงืŸ ืื•ืชื•.

ืœื›ืŸ - ื‘ื•ืื• ื—ืคืฉ "ื™ืฉื™ืจื•ืช ื‘ืžืกื“ ื”ื ืชื•ื ื™ื". ืœืžืจื‘ื” ื”ืžื–ืœ, PostgreSQL ืžืืคืฉืจ ืœื ื• ืœืขืฉื•ืช ื–ืืช, ื•ืœื ืจืง ืืคืฉืจื•ืช ืื—ืช - ื ื‘ื—ืŸ ืื•ืชื.

1.1: ืชืช ืžื—ืจื•ื–ืช "ื›ื ื”".

ืื ื• ื ืื—ื–ื™ื ื‘ืžื™ืœื” "ืžื—ืจื•ื–ืช ืžืฉื ื”". ืื‘ืœ ืœื—ื™ืคื•ืฉ ืื™ื ื“ืงืก ืœืคื™ ืžื—ืจื•ื–ืช ืžืฉื ื” (ื•ืืคื™ืœื• ืœืคื™ ื‘ื™ื˜ื•ื™ื™ื ืจื’ื•ืœืจื™ื™ื!) ื™ืฉ ืžืฆื•ื™ืŸ ืžื•ื“ื•ืœ pg_trgm! ืจืง ืื– ื™ื”ื™ื” ืฆื•ืจืš ืœืžื™ื™ืŸ ื ื›ื•ืŸ.

ื‘ื•ืื• ื ื ืกื” ืœืงื—ืช ืืช ื”ืฆืœื—ืช ื”ื‘ืื” ื›ื“ื™ ืœืคืฉื˜ ืืช ื”ื“ื’ื:

CREATE TABLE firms(
  id
    serial
      PRIMARY KEY
, name
    text
);

ืื ื—ื ื• ืžืขืœื™ื ืฉื 7.8 ืžื™ืœื™ื•ืŸ ืจืฉื•ืžื•ืช ืฉืœ ืืจื’ื•ื ื™ื ืืžื™ืชื™ื™ื ื•ืžื•ืกืคื™ื ืื•ืชื ืœืื™ื ื“ืงืก:

CREATE EXTENSION pg_trgm;
CREATE INDEX ON firms USING gin(lower(name) gin_trgm_ops);

ื‘ื•ืื• ื ื—ืคืฉ ืืช 10 ื”ืจืฉื•ืžื•ืช ื”ืจืืฉื•ื ื•ืช ืœื—ื™ืคื•ืฉ ื‘ื™ืŸ-ืœื™ื ืืจื™:

SELECT
  *
FROM
  firms
WHERE
  lower(name) ~ ('(^|s)' || 'ั€ะพะทะฐ')
ORDER BY
  lower(name) ~ ('^' || 'ั€ะพะทะฐ') DESC -- ัะฝะฐั‡ะฐะปะฐ "ะฝะฐั‡ะธะฝะฐัŽั‰ะธะตัั ะฝะฐ"
, lower(name) -- ะพัั‚ะฐะปัŒะฝะพะต ะฟะพ ะฐะปั„ะฐะฒะธั‚ัƒ
LIMIT 10;

PostgreSQL Antipatterns: ืกื™ืคื•ืจ ืขืœ ื—ื™ื“ื•ื“ ืื™ื˜ืจื˜ื™ื‘ื™ ืฉืœ ื—ื™ืคื•ืฉ ืœืคื™ ืฉื, ืื• "ืื•ืคื˜ื™ืžื™ื–ืฆื™ื” ืงื“ื™ืžื” ื•ืื—ื•ืจื”"
[ื”ืกืชื›ืœ ื‘-explain.tensor.ru]

ื•ื‘ื›ืŸ, ื›ื–ื”... 26ms, 31MB ืงืจื ื ืชื•ื ื™ื ื•ื™ื•ืชืจ ืž-1.7K ืจืฉื•ืžื•ืช ืžืกื•ื ื ื•ืช - ืขื‘ื•ืจ 10 ืจืฉื•ืžื•ืช ืฉื—ื™ืคืฉื•. ืขืœื•ื™ื•ืช ื”ืชืงื•ืจื” ื’ื‘ื•ื”ื•ืช ืžื“ื™, ืื™ืŸ ืžืฉื”ื• ื™ื•ืชืจ ื™ืขื™ืœ?

1.2: ืœื—ืคืฉ ืœืคื™ ื˜ืงืกื˜? ื–ื” FTS!

ื•ืื›ืŸ, PostgreSQL ืžืกืคืง ืขื•ืฆืžื” ืžืื•ื“ ืžื ื•ืข ื—ื™ืคื•ืฉ ื˜ืงืกื˜ ืžืœื (ื—ื™ืคื•ืฉ ื˜ืงืกื˜ ืžืœื), ื›ื•ืœืœ ื™ื›ื•ืœืช ื—ื™ืคื•ืฉ ืงื™ื“ื•ืžืช. ืืคืฉืจื•ืช ืžืฆื•ื™ื ืช, ืืชื” ืืคื™ืœื• ืœื ืฆืจื™ืš ืœื”ืชืงื™ืŸ ื”ืจื—ื‘ื•ืช! ื‘ื•ื ื ื ืกื”:

CREATE INDEX ON firms USING gin(to_tsvector('simple'::regconfig, lower(name)));

SELECT
  *
FROM
  firms
WHERE
  to_tsvector('simple'::regconfig, lower(name)) @@ to_tsquery('simple', 'ั€ะพะทะฐ:*')
ORDER BY
  lower(name) ~ ('^' || 'ั€ะพะทะฐ') DESC
, lower(name)
LIMIT 10;

PostgreSQL Antipatterns: ืกื™ืคื•ืจ ืขืœ ื—ื™ื“ื•ื“ ืื™ื˜ืจื˜ื™ื‘ื™ ืฉืœ ื—ื™ืคื•ืฉ ืœืคื™ ืฉื, ืื• "ืื•ืคื˜ื™ืžื™ื–ืฆื™ื” ืงื“ื™ืžื” ื•ืื—ื•ืจื”"
[ื”ืกืชื›ืœ ื‘-explain.tensor.ru]

ื›ืืŸ ื”ืงื‘ื™ืœื” ืฉืœ ื‘ื™ืฆื•ืข ืฉืื™ืœืชื” ืขื–ืจื” ืœื ื• ืžืขื˜, ื•ืงื™ืฆืฆื” ืืช ื”ื–ืžืŸ ื‘ื—ืฆื™ ืœ 11 ืืœืคื™ื•ืช ื”ืฉื ื™ื™ื”. ื•ื”ื™ื™ื ื• ืฆืจื™ื›ื™ื ืœืงืจื•ื ืคื™ 1.5 ืคื—ื•ืช - ื‘ืกืš ื”ื›ืœ 20MB. ืื‘ืœ ื›ืืŸ, ื›ืžื” ืฉืคื—ื•ืช, ื™ื•ืชืจ ื˜ื•ื‘, ื›ื™ ื›ื›ืœ ืฉื”ื ืคื— ืฉืื ื• ืงื•ืจืื™ื ื’ื“ื•ืœ ื™ื•ืชืจ, ื›ืš ื”ืกื™ื›ื•ื™ื™ื ืœืงื‘ืœ ืคืกืคื•ืก ืžื˜ืžื•ืŸ ื’ื‘ื•ื”ื™ื ื™ื•ืชืจ, ื•ื›ืœ ืขืžื•ื“ ื ื•ืกืฃ ืฉืœ ื ืชื•ื ื™ื ืฉื ืงืจื ืžื”ื“ื™ืกืง ืžื”ื•ื•ื” "ื‘ืœืžื™ื" ืคื•ื˜ื ืฆื™ืืœื™ื™ื ืœื‘ืงืฉื”.

1.3: ืขื“ื™ื™ืŸ ืื•ื”ื‘?

ื”ื‘ืงืฉื” ื”ืงื•ื“ืžืช ื˜ื•ื‘ื” ืœื›ื•ืœื, ืื‘ืœ ืจืง ืื ืชืžืฉื›ื• ืื•ืชื” ืžืื” ืืœืฃ ืคืขืžื™ื ื‘ื™ื•ื, ื”ื™ื ืชื’ื™ืข 2TB ืœืงืจื•ื ื ืชื•ื ื™ื. ื‘ืžืงืจื” ื”ื˜ื•ื‘, ืžื”ื–ื™ื›ืจื•ืŸ, ืื‘ืœ ืื ืื™ืŸ ืœืš ืžื–ืœ, ืื– ืžื”ื“ื™ืกืง. ืื– ื‘ื•ืื• ื ื ืกื” ืœื”ืงื˜ื™ืŸ ืื•ืชื•.

ื‘ื•ืื• ื ื–ื›ื•ืจ ืžื” ื”ืžืฉืชืžืฉ ืจื•ืฆื” ืœืจืื•ืช ื”ืจืืฉื•ืŸ "ืฉืžืชื—ื™ืœื™ื ื‘...". ืื– ื–ื” ื‘ืฆื•ืจืชื• ื”ื˜ื”ื•ืจื” ื‘ื™ื•ืชืจ ื—ื™ืคื•ืฉ ืงื™ื“ื•ืžืช ื‘ืืžืฆืขื•ืช text_pattern_ops! ื•ืจืง ืื "ืื™ืŸ ืœื ื• ืžืกืคื™ืง" ืขื“ 10 ืจืฉื•ืžื•ืช ืฉืื ื• ืžื—ืคืฉื™ื, ืื– ื ืฆื˜ืจืš ืœืกื™ื™ื ืœืงืจื•ื ืื•ืชืŸ ื‘ืืžืฆืขื•ืช ื—ื™ืคื•ืฉ FTS:

CREATE INDEX ON firms(lower(name) text_pattern_ops);

SELECT
  *
FROM
  firms
WHERE
  lower(name) LIKE ('ั€ะพะทะฐ' || '%')
LIMIT 10;

PostgreSQL Antipatterns: ืกื™ืคื•ืจ ืขืœ ื—ื™ื“ื•ื“ ืื™ื˜ืจื˜ื™ื‘ื™ ืฉืœ ื—ื™ืคื•ืฉ ืœืคื™ ืฉื, ืื• "ืื•ืคื˜ื™ืžื™ื–ืฆื™ื” ืงื“ื™ืžื” ื•ืื—ื•ืจื”"
[ื”ืกืชื›ืœ ื‘-explain.tensor.ru]

ื‘ื™ืฆื•ืขื™ื ืžืฆื•ื™ื ื™ื - ืกื”"ื› 0.05ms ื•ืงืฆืช ื™ื•ืชืจ ืž-100KB ืœืงืจื•ื! ืจืง ืื ื—ื ื• ืฉื›ื—ื ื• ืžื™ื•ืŸ ืœืคื™ ืฉืื›ื“ื™ ืฉื”ืžืฉืชืžืฉ ืœื ื™ืœืš ืœืื™ื‘ื•ื“ ื‘ืชื•ืฆืื•ืช:

SELECT
  *
FROM
  firms
WHERE
  lower(name) LIKE ('ั€ะพะทะฐ' || '%')
ORDER BY
  lower(name)
LIMIT 10;

PostgreSQL Antipatterns: ืกื™ืคื•ืจ ืขืœ ื—ื™ื“ื•ื“ ืื™ื˜ืจื˜ื™ื‘ื™ ืฉืœ ื—ื™ืคื•ืฉ ืœืคื™ ืฉื, ืื• "ืื•ืคื˜ื™ืžื™ื–ืฆื™ื” ืงื“ื™ืžื” ื•ืื—ื•ืจื”"
[ื”ืกืชื›ืœ ื‘-explain.tensor.ru]

ืื”, ืžืฉื”ื• ื›ื‘ืจ ืœื ื›ืœ ื›ืš ื™ืคื” - ื ืจืื” ื›ืื™ืœื• ื™ืฉ ืื™ื ื“ืงืก, ืื‘ืœ ื”ืžื™ื•ืŸ ืขืฃ ืขืœ ืคื ื™ื•... ื”ื•ื, ื›ืžื•ื‘ืŸ, ื›ื‘ืจ ื”ืจื‘ื” ืคืขืžื™ื ื™ื•ืชืจ ื™ืขื™ืœ ืžื”ืื•ืคืฆื™ื” ื”ืงื•ื“ืžืช, ืื‘ืœ...

1.4: "ืกื™ื™ื ืขื ืงื•ื‘ืฅ"

ืื‘ืœ ื™ืฉ ืื™ื ื“ืงืก ืฉืžืืคืฉืจ ืœืš ืœื—ืคืฉ ืœืคื™ ื˜ื•ื•ื— ื•ืขื“ื™ื™ืŸ ืœื”ืฉืชืžืฉ ื‘ืžื™ื•ืŸ ื›ืจื’ื™ืœ - btree ืจื’ื™ืœ!

CREATE INDEX ON firms(lower(name));

ืจืง ืืช ื”ื‘ืงืฉื” ืขื‘ื•ืจื• ื™ื”ื™ื” "ืœืืกื•ืฃ ื‘ืื•ืคืŸ ื™ื“ื ื™":

SELECT
  *
FROM
  firms
WHERE
  lower(name) >= 'ั€ะพะทะฐ' AND
  lower(name) <= ('ั€ะพะทะฐ' || chr(65535)) -- ะดะปั UTF8, ะดะปั ะพะดะฝะพะฑะฐะนั‚ะพะฒั‹ั… - chr(255)
ORDER BY
   lower(name)
LIMIT 10;

PostgreSQL Antipatterns: ืกื™ืคื•ืจ ืขืœ ื—ื™ื“ื•ื“ ืื™ื˜ืจื˜ื™ื‘ื™ ืฉืœ ื—ื™ืคื•ืฉ ืœืคื™ ืฉื, ืื• "ืื•ืคื˜ื™ืžื™ื–ืฆื™ื” ืงื“ื™ืžื” ื•ืื—ื•ืจื”"
[ื”ืกืชื›ืœ ื‘-explain.tensor.ru]

ืžืฆื•ื™ืŸ - ื”ืžื™ื•ืŸ ืขื•ื‘ื“, ื•ืฆืจื™ื›ืช ื”ืžืฉืื‘ื™ื ื ืฉืืจืช "ืžื™ืงืจื•ืกืงื•ืคื™ืช", ื™ืขื™ืœ ืคื™ ืืœืคื™ ืž-FTS "ื˜ื”ื•ืจ".! ื›ืœ ืžื” ืฉื ื•ืชืจ ื”ื•ื ืœื—ื‘ืจ ืื•ืชื• ืœื‘ืงืฉื” ืื—ืช:

(
  SELECT
    *
  FROM
    firms
  WHERE
    lower(name) >= 'ั€ะพะทะฐ' AND
    lower(name) <= ('ั€ะพะทะฐ' || chr(65535)) -- ะดะปั UTF8, ะดะปั ะพะดะฝะพะฑะฐะนั‚ะพะฒั‹ั… ะบะพะดะธั€ะพะฒะพะบ - chr(255)
  ORDER BY
     lower(name)
  LIMIT 10
)
UNION ALL
(
  SELECT
    *
  FROM
    firms
  WHERE
    to_tsvector('simple'::regconfig, lower(name)) @@ to_tsquery('simple', 'ั€ะพะทะฐ:*') AND
    lower(name) NOT LIKE ('ั€ะพะทะฐ' || '%') -- "ะฝะฐั‡ะธะฝะฐัŽั‰ะธะตัั ะฝะฐ" ะผั‹ ัƒะถะต ะฝะฐัˆะปะธ ะฒั‹ัˆะต
  ORDER BY
    lower(name) ~ ('^' || 'ั€ะพะทะฐ') DESC -- ะธัะฟะพะปัŒะทัƒะตะผ ั‚ัƒ ะถะต ัะพั€ั‚ะธั€ะพะฒะบัƒ, ั‡ั‚ะพะฑั‹ ะะ• ะฟะพะนั‚ะธ ะฟะพ btree-ะธะฝะดะตะบััƒ
  , lower(name)
  LIMIT 10
)
LIMIT 10;

ืฉื™ื ืœื‘ ืฉืฉืื™ืœืชืช ื”ืžืฉื ื” ื”ืฉื ื™ื™ื” ืžื‘ื•ืฆืขืช ืจืง ืื ื”ืจืืฉื•ืŸ ื”ื—ื–ื™ืจ ืคื—ื•ืช ืžื”ืฆืคื•ื™ ืื—ืจื•ืŸ LIMIT ืžืกืคืจ ืฉื•ืจื•ืช. ืื ื™ ืžื“ื‘ืจ ืขืœ ื”ืฉื™ื˜ื” ื”ื–ื• ืฉืœ ืื•ืคื˜ื™ืžื™ื–ืฆื™ื” ืฉืœ ืฉืื™ืœืชื•ืช ื›ื‘ืจ ื›ืชื‘ื• ืงื•ื“ื.

ืื– ื›ืŸ, ื™ืฉ ืœื ื• ืขื›ืฉื™ื• ื’ื btree ื•ื’ื ื’'ื™ืŸ ืขืœ ื”ืฉื•ืœื—ืŸ, ืื‘ืœ ืกื˜ื˜ื™ืกื˜ื™ืช ืžืกืชื‘ืจ ืฉื›ืŸ ืคื—ื•ืช ืž-10% ืžื”ื‘ืงืฉื•ืช ืžื’ื™ืขื•ืช ืœื‘ื™ืฆื•ืข ื”ื—ืกื™ืžื” ื”ืฉื ื™ื™ื”. ื›ืœื•ืžืจ, ืขื ืžื’ื‘ืœื•ืช ืื•ืคื™ื™ื ื™ื•ืช ื›ืืœื” ื™ื“ื•ืขื•ืช ืžืจืืฉ ืœืžืฉื™ืžื”, ื”ืฆืœื—ื ื• ืœื”ืคื—ื™ืช ืืช ื”ืฆืจื™ื›ื” ื”ื›ื•ืœืœืช ืฉืœ ืžืฉืื‘ื™ ื”ืฉืจืช ื‘ื›ืžืขื˜ ืคื™ ืืœืฃ!

1.5*: ืื ื—ื ื• ื™ื›ื•ืœื™ื ืœื”ืกืชื“ืจ ื‘ืœื™ ืงื•ื‘ืฅ

ืžืขืœ LIKE ื ืžื ืข ืžืื™ืชื ื• ืœื”ืฉืชืžืฉ ื‘ืžื™ื•ืŸ ืฉื’ื•ื™. ืื‘ืœ ื ื™ืชืŸ "ืœื”ื’ื“ื™ืจ ืื•ืชื• ื‘ื“ืจืš ื”ื ื›ื•ื ื”" ืขืœ ื™ื“ื™ ืฆื™ื•ืŸ ื”ืื•ืคืจื˜ื•ืจ USING:

ื›ื‘ืจื™ืจืช ืžื—ื“ืœ ื”ื™ื ืžื•ื ื—ืช ASC. ื‘ื ื•ืกืฃ, ื ื™ืชืŸ ืœืฆื™ื™ืŸ ืืช ื”ืฉื ืฉืœ ืื•ืคืจื˜ื•ืจ ืžื™ื•ืŸ ืกืคืฆื™ืคื™ ื‘ืกืขื™ืฃ USING. ืื•ืคืจื˜ื•ืจ ื”ืžื™ื•ืŸ ื—ื™ื™ื‘ ืœื”ื™ื•ืช ื—ื‘ืจ ืงื˜ืŸ ืž- ืื• ื’ื“ื•ืœ ืžืžืฉืคื—ืช ืื•ืคืจื˜ื•ืจื™ื ืฉืœ ืขืฅ B. ASC ื‘ื“ืจืš ื›ืœืœ ืฉื•ื•ื” ืขืจืš USING < ะธ DESC ื‘ื“ืจืš ื›ืœืœ ืฉื•ื•ื” ืขืจืš USING >.

ื‘ืžืงืจื” ืฉืœื ื•, "ืคื—ื•ืช" ื–ื” ~<~:

SELECT
  *
FROM
  firms
WHERE
  lower(name) LIKE ('ั€ะพะทะฐ' || '%')
ORDER BY
  lower(name) USING ~<~
LIMIT 10;

PostgreSQL Antipatterns: ืกื™ืคื•ืจ ืขืœ ื—ื™ื“ื•ื“ ืื™ื˜ืจื˜ื™ื‘ื™ ืฉืœ ื—ื™ืคื•ืฉ ืœืคื™ ืฉื, ืื• "ืื•ืคื˜ื™ืžื™ื–ืฆื™ื” ืงื“ื™ืžื” ื•ืื—ื•ืจื”"
[ื”ืกืชื›ืœ ื‘-explain.tensor.ru]

2: ืื™ืš ื‘ืงืฉื•ืช ืžื—ืžืฆื•ืช

ื›ืขืช ืื ื• ืžืฉืื™ืจื™ื ืืช ื‘ืงืฉืชื ื• "ืœื”ืชื‘ืขื‘ืข" ืœืžืฉืš ืฉื™ืฉื” ื—ื•ื“ืฉื™ื ืื• ืฉื ื”, ื•ืื ื• ืžื•ืคืชืขื™ื ืœืžืฆื•ื ืื•ืชื” ืฉื•ื‘ "ื‘ืคืกื’ื”" ืขื ืื™ื ื“ื™ืงื˜ื•ืจื™ื ืฉืœ ื”"ืฉืื™ื‘ื”" ื”ื™ื•ืžื™ืช ื”ื›ื•ืœืœืช ืฉืœ ื”ื–ื™ื›ืจื•ืŸ (ืžืื’ืจื™ื ืžืฉื•ืชืคื™ื) ื‘ 5.5TB - ื›ืœื•ืžืจ, ืืคื™ืœื• ื™ื•ืชืจ ืžืžื” ืฉื”ื™ื” ื‘ืžืงื•ืจ.

ืœื, ื›ืžื•ื‘ืŸ, ื”ืขืกืง ืฉืœื ื• ื’ื“ืœ ื•ืขื•ืžืก ื”ืขื‘ื•ื“ื” ืฉืœื ื• ื’ื“ืœ, ืื‘ืœ ืœื ื‘ืื•ืชื” ื›ืžื•ืช! ื–ื” ืื•ืžืจ ืฉืžืฉื”ื• ื›ืืŸ ื“ื’ื™ - ื‘ื•ืื• ื ื‘ื™ืŸ ืืช ื–ื”.

2.1: ื”ื•ืœื“ืช ื”ื”ื—ืœืคื”

ื‘ืฉืœื‘ ืžืกื•ื™ื, ืฆื•ื•ืช ืคื™ืชื•ื— ืื—ืจ ืจืฆื” ืœืืคืฉืจ "ืœืงืคื•ืฅ" ืžื—ื™ืคื•ืฉ ืžื ื•ื™ ืžื”ื™ืจ ืœืจื™ืฉื•ื ืขื ืชื•ืฆืื•ืช ื–ื”ื•ืช, ืืš ืžื•ืจื—ื‘ื•ืช. ืžื”ื• ืจื™ืฉื•ื ืœืœื ื ื™ื•ื•ื˜ ื‘ื“ืคื™ื? ื‘ื•ืื• ื ื“ืคืง ืืช ื–ื”!

( ... LIMIT <N> + 10)
UNION ALL
( ... LIMIT <N> + 10)
LIMIT 10 OFFSET <N>;

ื›ืขืช ื ื™ืชืŸ ื”ื™ื” ืœื”ืฆื™ื’ ืืช ื”ืจื™ืฉื•ื ืฉืœ ืชื•ืฆืื•ืช ื”ื—ื™ืคื•ืฉ ืขื ื˜ืขื™ื ืช "ืขืžื•ื“ ืื—ืจ ืขืžื•ื“" ืœืœื ื›ืœ ืœื—ืฅ ืขื‘ื•ืจ ื”ืžืคืชื—.

ื›ืžื•ื‘ืŸ, ืœืžืขืฉื”, ืขื‘ื•ืจ ื›ืœ ืขืžื•ื“ ืื—ืจ ืฉืœ ื ืชื•ื ื™ื ื ืงืจื ื™ื•ืชืจ ื•ื™ื•ืชืจ (ื”ื›ืœ ืžื”ืคืขื ื”ืงื•ื“ืžืช, ืื•ืชื” ื ื–ืจื•ืง, ื‘ืชื•ืกืคืช ื”"ื–ื ื‘") ื”ื“ืจื•ืฉ) - ื›ืœื•ืžืจ, ื–ื”ื• ืื ื˜ื™-ืชื‘ื ื™ืช ื‘ืจื•ืจื”. ืื‘ืœ ื™ื”ื™ื” ื ื›ื•ืŸ ื™ื•ืชืจ ืœื”ืชื—ื™ืœ ืืช ื”ื—ื™ืคื•ืฉ ื‘ืื™ื˜ืจืฆื™ื” ื”ื‘ืื” ืžื”ืžืคืชื— ื”ืžืื•ื—ืกืŸ ื‘ืžืžืฉืง, ืื‘ืœ ืขืœ ื›ืš ื‘ืคืขื ืื—ืจืช.

2.2: ืื ื™ ืจื•ืฆื” ืžืฉื”ื• ืืงื–ื•ื˜ื™

ื‘ืฉืœื‘ ืžืกื•ื™ื ื”ื™ื–ื ืจืฆื” ืœื’ื•ื•ืŸ ืืช ื”ืžื“ื’ื ื”ืžืชืงื‘ืœ ืขื ื ืชื•ื ื™ื ืžื˜ื‘ืœื” ืื—ืจืช, ืฉืœื’ื‘ื™ื” ื ืฉืœื—ื” ื›ืœ ื”ื‘ืงืฉื” ื”ืงื•ื“ืžืช ืœ-CTE:

WITH q AS (
  ...
  LIMIT <N> + 10
)
SELECT
  *
, (SELECT ...) sub_query -- ะบะฐะบะพะน-ั‚ะพ ะทะฐะฟั€ะพั ะบ ัะฒัะทะฐะฝะฝะพะน ั‚ะฐะฑะปะธั†ะต
FROM
  q
LIMIT 10 OFFSET <N>;

ื•ืœืžืจื•ืช ื–ืืช, ื–ื” ืœื ืจืข, ืฉื›ืŸ ืฉืื™ืœืชืช ื”ืžืฉื ื” ืžื•ืขืจื›ืช ืจืง ืขื‘ื•ืจ 10 ืจืฉื•ืžื•ืช ืฉื”ื•ื—ื–ืจื•, ืื ืœื ...

2.3: DISTINCT ื”ื•ื ื—ืกืจ ื”ื™ื’ื™ื•ืŸ ื•ื—ืกืจ ืจื—ืžื™ื

ืื™ืคืฉื”ื• ื‘ืชื”ืœื™ืš ืฉืœ ืื‘ื•ืœื•ืฆื™ื” ื›ื–ื• ืžืฉืื™ืœืชืช ื”ืžืฉื ื” ื”ืฉื ื™ื™ื” ืึธื‘ึตื“ NOT LIKE ืžืฆื‘. ื‘ืจื•ืจ ืฉืื—ืจื™ ื–ื” UNION ALL ื”ืชื—ื™ืœื• ืœื—ื–ื•ืจ ื›ืžื” ืขืจื›ื™ื ืคืขืžื™ื™ื - ื ืžืฆื ืชื—ื™ืœื” ื‘ืชื—ื™ืœืช ื”ืฉื•ืจื”, ื•ืื—ืจ ื›ืš ืฉื•ื‘ - ื‘ืชื—ื™ืœืช ื”ืžื™ืœื” ื”ืจืืฉื•ื ื” ืฉืœ ืฉื•ืจื” ื–ื•. ื‘ืžื’ื‘ืœื”, ื›ืœ ื”ืจืฉื•ืžื•ืช ืฉืœ ืฉืื™ืœืชืช ื”ืžืฉื ื” ื”ืฉื ื™ื™ื” ื™ื›ื•ืœื•ืช ืœื”ืชืื™ื ืœืจืฉื•ืžื•ืช ืฉืœ ื”ืจืืฉื•ื ื”.

ืžื” ืขื•ืฉื” ืžืคืชื— ื‘ืžืงื•ื ืœื—ืคืฉ ืืช ื”ืกื™ื‘ื”?.. ืื™ืŸ ืฉืืœื”!

  • ืœื”ื›ืคื™ืœ ืืช ื”ื’ื•ื“ืœ ื“ื•ื’ืžืื•ืช ืžืงื•ืจื™ื•ืช
  • ืœื”ื—ื™ืœ DISTINCTื›ื“ื™ ืœืงื‘ืœ ืจืง ืžื•ืคืขื™ื ื‘ื•ื“ื“ื™ื ืฉืœ ื›ืœ ืฉื•ืจื”

WITH q AS (
  ( ... LIMIT <2 * N> + 10)
  UNION ALL
  ( ... LIMIT <2 * N> + 10)
  LIMIT <2 * N> + 10
)
SELECT DISTINCT
  *
, (SELECT ...) sub_query
FROM
  q
LIMIT 10 OFFSET <N>;

ื›ืœื•ืžืจ, ื‘ืจื•ืจ ืฉื”ืชื•ืฆืื”, ื‘ืกื•ืคื• ืฉืœ ื“ื‘ืจ, ื–ื”ื” ืœื—ืœื•ื˜ื™ืŸ, ืื‘ืœ ื”ืกื™ื›ื•ื™ "ืœืขื•ืฃ" ืœืชื•ืš ืชืช-ื”ืฉืื™ืœืชื” ืฉืœ CTE 2 ื”ืคืš ืœื”ืจื‘ื” ื™ื•ืชืจ ื’ื‘ื•ื”, ื•ื’ื ื‘ืœื™ ื–ื”, ื‘ืจื•ืจ ื™ื•ืชืจ ืงืจื™ื.

ืื‘ืœ ื–ื” ืœื ื”ื“ื‘ืจ ื”ื›ื™ ืขืฆื•ื‘. ืžืื– ื”ืžืคืชื— ื‘ื™ืงืฉ ืœื‘ื—ื•ืจ DISTINCT ืœื ืขื‘ื•ืจ ืืœื” ืกืคืฆื™ืคื™ื™ื, ืืœื ืขื‘ื•ืจ ื›ืœ ื”ืฉื“ื•ืช ื‘ื‘ืช ืื—ืช ืจืฉื•ืžื•ืช, ื•ืื– ื”ืฉื“ื” sub_query - ื”ืชื•ืฆืื” ืฉืœ ืฉืื™ืœืชืช ื”ืžืฉื ื” - ื ื›ืœืœ ืฉื ื‘ืื•ืคืŸ ืื•ื˜ื•ืžื˜ื™. ืขื›ืฉื™ื•, ืœื‘ื™ืฆื•ืข DISTINCT, ืžืกื“ ื”ื ืชื•ื ื™ื ื”ื™ื” ืฆืจื™ืš ืœื”ืคืขื™ืœ ื›ื‘ืจ ืœื 10 ืฉืื™ืœืชื•ืช ืžืฉื ื”, ืืœื ื›ื•ืœืŸ <2 * N> + 10!

2.4: ืฉื™ืชื•ืฃ ืคืขื•ืœื” ืžืขืœ ื”ื›ืœ!

ืื–, ื”ืžืคืชื—ื™ื ื—ื™ื• - ื”ื ืœื ื”ื˜ืจื™ื—ื•, ื›ื™ ื‘ืจื•ืจ ืฉืœืžืฉืชืžืฉ ืœื ื”ื™ื™ืชื” ืžืกืคื™ืง ืกื‘ืœื ื•ืช "ืœื”ืชืื™ื" ืืช ื”ืจื™ืฉื•ื ืœืขืจื›ื™ N ืžืฉืžืขื•ืชื™ื™ื ืขื ื”ืื˜ื” ื›ืจื•ื ื™ืช ื‘ืงื‘ืœืช ื›ืœ "ืขืžื•ื“" ืขื•ืงื‘.

ืขื“ ืฉื”ื’ื™ืขื• ืืœื™ื”ื ืžืคืชื—ื™ื ืžืžื—ืœืงื” ืื—ืจืช ื•ืจืฆื• ืœื”ืฉืชืžืฉ ื‘ืฉื™ื˜ื” ื›ืœ ื›ืš ื ื•ื—ื” ืœื—ื™ืคื•ืฉ ืื™ื˜ืจื˜ื™ื‘ื™ - ื›ืœื•ืžืจ, ืื ื—ื ื• ืœื•ืงื—ื™ื ื—ืชื™ื›ื” ืžื“ื’ื™ืžื” ื›ืœืฉื”ื™, ืžืกื ื ื™ื ืื•ืชื” ืœืคื™ ืชื ืื™ื ื ื•ืกืคื™ื, ืžืฆื™ื™ืจื™ื ืืช ื”ืชื•ืฆืื”, ื•ืื– ืืช ื”ื—ืœืง ื”ื‘ื (ืฉื‘ืžืงืจื” ืฉืœื ื• ืžื•ืฉื’ืช ืขืœ ื™ื“ื™ ื”ื’ื“ืœืช N), ื•ื›ืš ื”ืœืื” ืขื“ ืฉื ืžืœื ืืช ื”ืžืกืš.

ื‘ืื•ืคืŸ ื›ืœืœื™, ื‘ื“ื’ื™ืžื” ืฉื ืชืคืกื” N ื”ื’ื™ืข ืœืขืจื›ื™ื ืฉืœ ื›ืžืขื˜ 17K, ื•ื‘ืชื•ืš ื™ื•ื ืื—ื“ ื‘ืœื‘ื“ ืœืคื—ื•ืช 4K ืžื‘ืงืฉื•ืช ื›ืืœื” ื‘ื•ืฆืขื• "ืœืื•ืจืš ื”ืฉืจืฉืจืช". ื”ืื—ืจื•ื ื™ื ืฉื‘ื”ื ื ืกืจืงื• ื‘ืื•ืžืฅ ืขืœ ื™ื“ื™ 1GB ื–ื™ื›ืจื•ืŸ ืœื›ืœ ืื™ื˜ืจืฆื™ื”...

ื‘ืกืš ื”ื›ืœ

PostgreSQL Antipatterns: ืกื™ืคื•ืจ ืขืœ ื—ื™ื“ื•ื“ ืื™ื˜ืจื˜ื™ื‘ื™ ืฉืœ ื—ื™ืคื•ืฉ ืœืคื™ ืฉื, ืื• "ืื•ืคื˜ื™ืžื™ื–ืฆื™ื” ืงื“ื™ืžื” ื•ืื—ื•ืจื”"

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

ื”ื•ืกืคืช ืชื’ื•ื‘ื”