PostgreSQL Antipatterns: skealike JOIN's en OR's

Π‘ΠΎΠΉΡ‚Π΅ΡΡŒ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ, buffers приносящих…
На ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ нСбольшого запроса рассмотрим Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΡƒΠ½ΠΈΠ²Π΅Ρ€ΡΠ°Π»ΡŒΠ½Ρ‹Π΅ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Ρ‹ ΠΊ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ запросов Π½Π° PostgreSQL. ΠŸΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ ΠΈΠΌΠΈ ΠΈΠ»ΠΈ Π½Π΅Ρ‚ β€” Π²Ρ‹Π±ΠΈΡ€Π°Ρ‚ΡŒ Π²Π°ΠΌ, Π½ΠΎ Π·Π½Π°Ρ‚ΡŒ ΠΎ Π½ΠΈΡ… стоит.

Π’ ΠΊΠ°ΠΊΠΈΡ…-Ρ‚ΠΎ ΠΏΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΡ… вСрсиях PG ситуация ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒΡΡ с Β«ΠΏΠΎΡƒΠΌΠ½Π΅Π½ΠΈΠ΅ΠΌΒ» ΠΏΠ»Π°Π½ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΠ°, Π½ΠΎ для 9.4/9.6 ΠΎΠ½Π° выглядит ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π½ΠΎ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΠΎ, ΠΊΠ°ΠΊ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ Ρ‚ΡƒΡ‚.

Π’ΠΎΠ·ΡŒΠΌΡƒ Π²ΠΏΠΎΠ»Π½Π΅ Ρ€Π΅Π°Π»ΡŒΠ½Ρ‹ΠΉ запрос:

SELECT
  TRUE
FROM
  "Π”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚" d
INNER JOIN
  "Π”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅" doc_ex
    USING("@Π”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚")
INNER JOIN
  "Π’ΠΈΠΏΠ”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°" t_doc ON
    t_doc."@Π’ΠΈΠΏΠ”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°" = d."Π’ΠΈΠΏΠ”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°"
WHERE
  (d."Π›ΠΈΡ†ΠΎ3" = 19091 or d."Π‘ΠΎΡ‚Ρ€ΡƒΠ΄Π½ΠΈΠΊ" = 19091) AND
  d."$Π§Π΅Ρ€Π½ΠΎΠ²ΠΈΠΊ" IS NULL AND
  d."Π£Π΄Π°Π»Π΅Π½" IS NOT TRUE AND
  doc_ex."БостояниС"[1] IS TRUE AND
  t_doc."Π’ΠΈΠΏΠ”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°" = 'ΠŸΠ»Π°Π½Π Π°Π±ΠΎΡ‚'
LIMIT 1;

ΠΏΡ€ΠΎ ΠΈΠΌΠ΅Π½Π° Ρ‚Π°Π±Π»ΠΈΡ† ΠΈ ΠΏΠΎΠ»Π΅ΠΉDe "Russyske" nammen fan fjilden en tabellen kinne oars wurde behannele, mar dit is in kwestje fan smaak. Fanwege de hjir by Tensor d'r binne gjin bΓ»tenlΓ’nske Γ»ntwikkelders, en PostgreSQL lit ΓΊs nammen jaan, sels yn hiΓ«roglyfen, as se ynsletten yn quotes, dan neame wy objekten it leafst Γ»ndΓ»belsinnich en dΓΊdlik, sadat der gjin diskrepΓ’nsjes binne.
ΠŸΠΎΡΠΌΠΎΡ‚Ρ€ΠΈΠΌ Π½Π° ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ²ΡˆΠΈΠΉΡΡ ΠΏΠ»Π°Π½:
PostgreSQL Antipatterns: skealike JOIN's en OR's
[sjoch op explain.tensor.ru]

144ms ΠΈ ΠΏΠΎΡ‡Ρ‚ΠΈ 53K buffers β€” Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ большС 400MB Π΄Π°Π½Π½Ρ‹Ρ…! И Π½Π°ΠΌ ΠΏΠΎΠ²Π΅Π·Π΅Ρ‚, Ссли всС ΠΎΠ½ΠΈ окаТутся Π² кэшС ΠΊ ΠΌΠΎΠΌΠ΅Π½Ρ‚Ρƒ нашСго запроса, ΠΈΠ½Π°Ρ‡Π΅ ΠΎΠ½ станСт Π² Ρ€Π°Π·Ρ‹ дольшС ΠΏΡ€ΠΈ Π²Ρ‹Ρ‡ΠΈΡ‚Ρ‹Π²Π°Π½ΠΈΠΈ с диска.

Алгоритм Π²Π°ΠΆΠ½Π΅Π΅ всСго!

Π§Ρ‚ΠΎΠ±Ρ‹ ΠΊΠ°ΠΊ-Ρ‚ΠΎ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ любой запрос, Π½Π°Π΄ΠΎ сначала ΠΏΠΎΠ½ΡΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ ΠΆΠ΅ ΠΎΠ½ Π²ΠΎΠΎΠ±Ρ‰Π΅ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π΄Π΅Π»Π°Ρ‚ΡŒ.
ΠžΡΡ‚Π°Π²ΠΈΠΌ ΠΏΠΎΠΊΠ° Π·Π° Ρ€Π°ΠΌΠΊΠ°ΠΌΠΈ этой ΡΡ‚Π°Ρ‚ΡŒΠΈ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ самой структуры Π‘Π”, ΠΈ договоримся, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ «дСшСво» ΠΏΠ΅Ρ€Π΅ΠΏΠΈΡΠ°Ρ‚ΡŒ запрос ΠΈ/ΠΈΠ»ΠΈ Π½Π°ΠΊΠ°Ρ‚ΠΈΡ‚ΡŒ Π½Π° Π±Π°Π·Ρƒ ΠΊΠ°ΠΊΠΈΠ΅-Ρ‚ΠΎ Π½ΡƒΠΆΠ½Ρ‹Π΅ Π½Π°ΠΌ yndeksen.

Π˜Ρ‚Π°ΠΊ, запрос:
β€” провСряСт сущСствованиС Ρ…ΠΎΡ‚ΡŒ ΠΊΠ°ΠΊΠΎΠ³ΠΎ-Ρ‚ΠΎ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°
β€” Π² Π½ΡƒΠΆΠ½ΠΎΠΌ Π½Π°ΠΌ состоянии ΠΈ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ°
β€” Π³Π΄Π΅ Π°Π²Ρ‚ΠΎΡ€ΠΎΠΌ ΠΈΠ»ΠΈ исполнитСлСм являСтся Π½ΡƒΠΆΠ½Ρ‹ΠΉ Π½Π°ΠΌ сотрудник

JOIN + LIMIT 1

Достаточно часто Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΡƒ ΠΏΡ€ΠΎΡ‰Π΅ Π½Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ запрос, Π³Π΄Π΅ сначала дСлаСтся соСдинСниС большого количСства Ρ‚Π°Π±Π»ΠΈΡ†, Π° ΠΏΠΎΡ‚ΠΎΠΌ ΠΈΠ· всСго этого мноТСства остаСтся ΠΎΠ΄Π½Π°-СдинствСнная запись. Но ΠΏΡ€ΠΎΡ‰Π΅ для Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ° β€” Π½Π΅ Π·Π½Π°Ρ‡ΠΈΡ‚ эффСктивнСС для Π‘Π”.
Π’ нашСм случаС Ρ‚Π°Π±Π»ΠΈΡ† Π±Ρ‹Π»ΠΎ всСго 3 β€” Π° ΠΊΠ°ΠΊΠΎΠΉ эффСкт…

Π”Π°Π²Π°ΠΉΡ‚Π΅ для Π½Π°Ρ‡Π°Π»Π° избавимся ΠΎΡ‚ соСдинСния с Ρ‚Π°Π±Π»ΠΈΡ†Π΅ΠΉ Β«Π’ΠΈΠΏΠ”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Β», Π° Π·Π°ΠΎΠ΄Π½ΠΎ подскаТСм Π±Π°Π·Π΅, Ρ‡Ρ‚ΠΎ Ρƒ запись Ρ‚ΠΈΠΏΠ° Ρƒ нас ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Π° (ΠΌΡ‹-Ρ‚ΠΎ это Π·Π½Π°Π΅ΠΌ, Π° Π²ΠΎΡ‚ ΠΏΠ»Π°Π½ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊ ΠΏΠΎΠΊΠ° Π½Π΅ догадываСтся):

WITH T AS (
  SELECT
    "@Π’ΠΈΠΏΠ”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°"
  FROM
    "Π’ΠΈΠΏΠ”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°"
  WHERE
    "Π’ΠΈΠΏΠ”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°" = 'ΠŸΠ»Π°Π½Π Π°Π±ΠΎΡ‚'
  LIMIT 1
)
...
WHERE
  d."Π’ΠΈΠΏΠ”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°" = (TABLE T)
...

Π”Π°, Ссли Ρ‚Π°Π±Π»ΠΈΡ†Π°/CTE состоит ΠΈΠ· СдинствСнного поля СдинствСнной ΠΆΠ΅ записи, Ρ‚ΠΎ Π² PG ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΈΡΠ°Ρ‚ΡŒ Π΄Π°ΠΆΠ΅ Ρ‚Π°ΠΊ, вмСсто

d."Π’ΠΈΠΏΠ”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°" = (SELECT "@Π’ΠΈΠΏΠ”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°" FROM T LIMIT 1)

Β«Π›Π΅Π½ΠΈΠ²Ρ‹Π΅Β» вычислСния Π² запросах PostgreSQL

BitmapOr vs UNION

Π’ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… случаях Bitmap Heap Scan Π±ΡƒΠ΄Π΅Ρ‚ ΡΡ‚ΠΎΠΈΡ‚ΡŒ Π½Π°ΠΌ ΠΎΡ‡Π΅Π½ΡŒ Π΄ΠΎΡ€ΠΎΠ³ΠΎ β€” Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π² нашСй ситуации, ΠΊΠΎΠ³Π΄Π° достаточно ΠΌΠ½ΠΎΠ³ΠΎ записСй ΠΏΠΎΠ΄ΠΏΠ°Π΄Π°Π΅Ρ‚ ΠΏΠΎΠ΄ Ρ‚Ρ€Π΅Π±ΡƒΠ΅ΠΌΠΎΠ΅ условиС. ΠŸΠΎΠ»ΡƒΡ‡ΠΈΠ»ΠΈ ΠΌΡ‹ Π΅Π³ΠΎ ΠΈΠ·-Π·Π° OR-условия, ΠΏΡ€Π΅Π²Ρ€Π°Ρ‚ΠΈΠ²ΡˆΠ΅Π³ΠΎΡΡ Π² BitmapOr-ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ Π² ΠΏΠ»Π°Π½Π΅.
ВСрнСмся ΠΊ исходной Π·Π°Π΄Π°Ρ‡Π΅ β€” Π½Π°Π΄ΠΎ Π½Π°ΠΉΡ‚ΠΈ запись, ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΡƒΡŽ immen ΠΈΠ· условий β€” Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ Π½Π΅Π·Π°Ρ‡Π΅ΠΌ ΠΈΡΠΊΠ°Ρ‚ΡŒ всС 59K записСй ΠΏΠΎ ΠΎΠ±ΠΎΠΈΠΌ условиям. Π•ΡΡ‚ΡŒ способ ΠΎΡ‚Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ ΠΎΠ΄Π½ΠΎ условиС, Π° ΠΊΠΎ Π²Ρ‚ΠΎΡ€ΠΎΠΌΡƒ ΠΏΠ΅Ρ€Π΅ΠΉΡ‚ΠΈ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΊΠΎΠ³Π΄Π° ΠΏΠΎ ΠΏΠ΅Ρ€Π²ΠΎΠΌΡƒ Π½ΠΈΡ‡Π΅Π³ΠΎ Π½Π΅ нашлось. Нам ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ‚ такая конструкция:

(
  SELECT
    ...
  LIMIT 1
)
UNION ALL
(
  SELECT
    ...
  LIMIT 1
)
LIMIT 1

Β«Π’Π½Π΅ΡˆΠ½ΠΈΠΉΒ» LIMIT 1 Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚, Ρ‡Ρ‚ΠΎ поиск Π·Π°Π²Π΅Ρ€ΡˆΠΈΡ‚ΡΡ ΠΏΡ€ΠΈ Π½Π°Ρ…ΠΎΠΆΠ΄Π΅Π½ΠΈΠΈ ΠΏΠ΅Ρ€Π²ΠΎΠΉ ΠΆΠ΅ записи. И Ссли ΠΎΠ½Π° найдСтся ΡƒΠΆΠ΅ Π² ΠΏΠ΅Ρ€Π²ΠΎΠΌ Π±Π»ΠΎΠΊΠ΅, Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Π²Ρ‚ΠΎΡ€ΠΎΠ³ΠΎ ΠΎΡΡƒΡ‰Π΅ΡΡ‚Π²Π»ΡΡ‚ΡŒΡΡ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ (never executed Π² ΠΏΠ»Π°Π½Π΅).

Β«ΠŸΡ€ΡΡ‡Π΅ΠΌ ΠΏΠΎΠ΄ CASEΒ» слоТныС условия

Π’ исходном запросС Π΅ΡΡ‚ΡŒ ΠΊΡ€Π°ΠΉΠ½Π΅ Π½Π΅ΡƒΠ΄ΠΎΠ±Π½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚ β€” ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° состояния ΠΏΠΎ связанной Ρ‚Π°Π±Π»ΠΈΡ†Π΅ Β«Π”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅Β». НСзависимо ΠΎΡ‚ истинности ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Ρ… условий Π² Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠΈ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, d.Β«Π£Π΄Π°Π»Π΅Π½Β» IS NOT TRUE), это соСдинСниС выполняСтся всСгда ΠΈ «стоит рСсурсов». Π‘ΠΎΠ»ΡŒΡˆΠ΅ ΠΈΠ»ΠΈ мСньшС ΠΈΡ… Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠΎΡ‚Ρ€Π°Ρ‡Π΅Π½ΠΎ β€” зависит ΠΎΡ‚ объСма этой Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹.
Но ΠΌΠΎΠΆΠ½ΠΎ ΠΌΠΎΠ΄ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ запрос Ρ‚Π°ΠΊ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ поиск связанной записи происходил Π±Ρ‹ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΊΠΎΠ³Π΄Π° это Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ:

SELECT
  ...
FROM
  "Π”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚" d
WHERE
  ... /*index cond*/ AND
  CASE
    WHEN "$Π§Π΅Ρ€Π½ΠΎΠ²ΠΈΠΊ" IS NULL AND "Π£Π΄Π°Π»Π΅Π½" IS NOT TRUE THEN (
      SELECT
        "БостояниС"[1] IS TRUE
      FROM
        "Π”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅"
      WHERE
        "@Π”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚" = d."@Π”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚"
    )
  END

Π Π°Π· ΠΈΠ· связываСмой Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹ Π½Π°ΠΌ Π½Π΅ Π½ΡƒΠΆΠ½ΠΎ для Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° Π½ΠΈ ΠΎΠ΄Π½ΠΎ ΠΈΠ· ΠΏΠΎΠ»Π΅ΠΉ, Ρ‚ΠΎ ΠΌΡ‹ ΠΈΠΌΠ΅Π΅ΠΌ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ ΠΏΡ€Π΅Π²Ρ€Π°Ρ‚ΠΈΡ‚ΡŒ JOIN Π² условиС ΠΏΠΎ подзапросу.
ΠžΡΡ‚Π°Π²ΠΈΠΌ индСксируСмыС поля Β«Π·Π° скобками» CASE, простыС условия ΠΎΡ‚ записи вносим Π² WHEN-Π±Π»ΠΎΠΊ β€” ΠΈ Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ «тяТСлый» запрос выполняСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄Π΅ Π² THEN.

Моя фамилия Β«Π˜Ρ‚ΠΎΠ³ΠΎΒ»

Π‘ΠΎΠ±ΠΈΡ€Π°Π΅ΠΌ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠΉ запрос со всСми описанными Π²Ρ‹ΡˆΠ΅ ΠΌΠ΅Ρ…Π°Π½ΠΈΠΊΠ°ΠΌΠΈ:

WITH T AS (
  SELECT
    "@Π’ΠΈΠΏΠ”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°"
  FROM
    "Π’ΠΈΠΏΠ”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°"
  WHERE
    "Π’ΠΈΠΏΠ”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°" = 'ΠŸΠ»Π°Π½Π Π°Π±ΠΎΡ‚'
)
  (
    SELECT
      TRUE
    FROM
      "Π”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚" d
    WHERE
      ("Π›ΠΈΡ†ΠΎ3", "Π’ΠΈΠΏΠ”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°") = (19091, (TABLE T)) AND
      CASE
        WHEN "$Π§Π΅Ρ€Π½ΠΎΠ²ΠΈΠΊ" IS NULL AND "Π£Π΄Π°Π»Π΅Π½" IS NOT TRUE THEN (
          SELECT
            "БостояниС"[1] IS TRUE
          FROM
            "Π”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅"
          WHERE
            "@Π”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚" = d."@Π”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚"
        )
      END
    LIMIT 1
  )
UNION ALL
  (
    SELECT
      TRUE
    FROM
      "Π”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚" d
    WHERE
      ("Π’ΠΈΠΏΠ”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°", "Π‘ΠΎΡ‚Ρ€ΡƒΠ΄Π½ΠΈΠΊ") = ((TABLE T), 19091) AND
      CASE
        WHEN "$Π§Π΅Ρ€Π½ΠΎΠ²ΠΈΠΊ" IS NULL AND "Π£Π΄Π°Π»Π΅Π½" IS NOT TRUE THEN (
          SELECT
            "БостояниС"[1] IS TRUE
          FROM
            "Π”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅"
          WHERE
            "@Π”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚" = d."@Π”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚"
        )
      END
    LIMIT 1
  )
LIMIT 1;

ПодгоняСм [ΠΏΠΎΠ΄] индСксы

НамСтанный Π³Π»Π°Π· Π·Π°ΠΌΠ΅Ρ‚ΠΈΠ», Ρ‡Ρ‚ΠΎ индСксируСмыС условия Π² ΠΏΠΎΠ΄Π±Π»ΠΎΠΊΠ°Ρ… UNION Ρ‡ΡƒΡ‚ΡŒ разнятся β€” это ΠΏΠΎΡ‚ΠΎΠΌΡƒ, Ρ‡Ρ‚ΠΎ Ρƒ нас ΡƒΠΆΠ΅ Π΅ΡΡ‚ΡŒ подходящиС индСксы Π½Π° Ρ‚Π°Π±Π»ΠΈΡ†Π΅. А Ссли Π±Ρ‹ ΠΈΡ… Π½Π΅ Π±Ρ‹Π»ΠΎ β€” Ρ‚ΠΎ стоило Π±Ρ‹ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ: Π”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚(Π›ΠΈΡ†ΠΎ3, Π’ΠΈΠΏΠ”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°) ΠΈ Π”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚(Π’ΠΈΠΏΠ”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°, Π‘ΠΎΡ‚Ρ€ΡƒΠ΄Π½ΠΈΠΊ).
ΠΎ порядкС ΠΏΠΎΠ»Π΅ΠΉ Π² ROW-условияхБ Ρ‚ΠΎΡ‡ΠΊΠΈ зрСния ΠΏΠ»Π°Π½ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊΠ°, ΠΊΠΎΠ½Π΅Ρ‡Π½ΠΎ, ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ ΠΈ (A, B) = (constA, constB)en (B, A) = (constB, constA). Но ΠΏΡ€ΠΈ записи Π² порядкС слСдования ΠΏΠΎΠ»Π΅ΠΉ Π² индСксС, Ρ‚Π°ΠΊΠΎΠΉ запрос просто ΡƒΠ΄ΠΎΠ±Π½Π΅Π΅ ΠΏΠΎΡ‚ΠΎΠΌ ΠΎΡ‚Π»Π°ΠΆΠΈΠ²Π°Ρ‚ΡŒ.
Π§Ρ‚ΠΎ Π² ΠΏΠ»Π°Π½Π΅?
PostgreSQL Antipatterns: skealike JOIN's en OR's
[sjoch op explain.tensor.ru]

К соТалСнию, Π½Π°ΠΌ Π½Π΅ ΠΏΠΎΠ²Π΅Π·Π»ΠΎ, ΠΈ Π² ΠΏΠ΅Ρ€Π²ΠΎΠΌ UNION-Π±Π»ΠΎΠΊΠ΅ Π½ΠΈΡ‡Π΅Π³ΠΎ Π½Π΅ нашлось, поэтому Π²Ρ‚ΠΎΡ€ΠΎΠΉ всС-Ρ‚Π°ΠΊΠΈ пошСл Π½Π° Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅. Но Π΄Π°ΠΆΠ΅ ΠΏΡ€ΠΈ этом β€” всСго 0.037ms ΠΈ 11 buffers!
ΠœΡ‹ ускорили запрос ΠΈ сократили Β«ΠΏΡ€ΠΎΠΊΠ°Ρ‡ΠΊΡƒΒ» Π΄Π°Π½Π½Ρ‹Ρ… Π² памяти Π² нСсколько тысяч Ρ€Π°Π·, воспользовавшись достаточно простыми ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΈΠΊΠ°ΠΌΠΈ β€” Π½Π΅ΠΏΠ»ΠΎΡ…ΠΎΠΉ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΏΡ€ΠΈ нСбольшой копипастС. πŸ™‚

Boarne: www.habr.com

Add a comment