PostgreSQL Antipatterns: рдирд╛рдорджреНрд╡рд╛рд░рд╛ рдЦреЛрдЬрдХреЛ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдкрд░рд┐рд╖реНрдХрд░рдгрдХреЛ рдХрдерд╛, рд╡рд╛ "рдЕрдкреНрдЯрд┐рдорд╛рдЗрдЬреЗрд╕рди рдЕрдЧрд╛рдбрд┐ рд░ рдкрдЫрд╛рдбрд┐"

рджреЗрд╢рднрд░рдХрд╛ рдмрд┐рдХреНрд░реА рдХрд╛рд░реНрдпрд╛рд▓рдпрд╣рд░реВрдмрд╛рдЯ рд╣рдЬрд╛рд░реМрдВ рдкреНрд░рдмрдиреНрдзрдХрд╣рд░реВ рд░реЗрдХрд░реНрдб рдЫрдиреН рд╣рд╛рдореНрд░реЛ CRM рдкреНрд░рдгрд╛рд▓реА рджреИрдирд┐рдХ рд╣рдЬрд╛рд░реМрдВ рд╕рдореНрдкрд░реНрдХрд╣рд░реВ - рд╕рдореНрднрд╛рд╡рд┐рдд рд╡рд╛ рдЕрд╡рд╕реНрдерд┐рдд рдЧреНрд░рд╛рд╣рдХрд╣рд░реБ рд╕рдВрдЧ рд╕рдВрдЪрд╛рд░ рдХреЛ рддрдереНрдпрд╣рд░реБред рд░ рдпрд╕рдХреЛ рд▓рд╛рдЧрд┐, рддрдкрд╛рдИрдВрд▓реЗ рдкрд╣рд┐рд▓реЗ рдПрдХ рдЧреНрд░рд╛рд╣рдХ рдлреЗрд▓рд╛ рдкрд╛рд░реНрдиреБ рдкрд░реНрдЫ, рд░ рдЕрдзрд┐рдорд╛рдирддрдГ рдзреЗрд░реИ рдЪрд╛рдБрдбреИред рд░ рдпреЛ рдкреНрд░рд╛рдп: рдирд╛рдо рджреНрд╡рд╛рд░рд╛ рд╣реБрдиреНрдЫред

рддреНрдпрд╕рдХрд╛рд░рдг, рдпреЛ рдЕрдЪрдореНрдордХреЛ рдХреБрд░рд╛ рд╣реЛрдЗрди рдХрд┐, рдПрдХ рдкрдЯрдХ рдлреЗрд░рд┐ "рднрд╛рд░реА" рдкреНрд░рд╢реНрдирд╣рд░реВрдХреЛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдЧрд░реНрджрд╛ рд╕рдмреИрднрдиреНрджрд╛ рд▓реЛрдб рдЧрд░рд┐рдПрдХреЛ рдбрд╛рдЯрд╛рдмреЗрд╕рд╣рд░реВ - рд╣рд╛рдореНрд░реЛ рдЖрдлреНрдиреИред VLSI рдХрд░реНрдкреЛрд░реЗрдЯ рдЦрд╛рддрд╛, рдореИрд▓реЗ "рд╢реАрд░реНрд╖рдорд╛" рдлреЗрд▓рд╛ рдкрд╛рд░реЗ рдирд╛рдорджреНрд╡рд╛рд░рд╛ "рдЫрд┐рдЯреЛ" рдЦреЛрдЬрдХреЛ рд▓рд╛рдЧрд┐ рдЕрдиреБрд░реЛрдз рд╕рдВрдЧрдарди рдХрд╛рд░реНрдбрд╣рд░реВрдХреЛ рд▓рд╛рдЧрд┐ред

рдпрд╕рдмрд╛рд╣реЗрдХ рдердк рдЕрдиреБрд╕рдиреНрдзрд╛рдирд▓реЗ рдПрдЙрдЯрд╛ рд░реЛрдЪрдХ рдЙрджрд╛рд╣рд░рдг рджреЗрдЦрд╛рдпреЛ рдкрд╣рд┐рд▓реЛ рдЕрдиреБрдХреВрд▓рди рд░ рддреНрдпрд╕рдкрдЫрд┐ рдкреНрд░рджрд░реНрд╢рди рдЧрд┐рд░рд╛рд╡рдЯ рдзреЗрд░реИ рдЯреЛрд▓реАрд╣рд░реВ рджреНрд╡рд╛рд░рд╛ рдпрд╕рдХреЛ рдХреНрд░рдорд┐рдХ рдкрд░рд┐рд╖реНрдХрд░рдгрдХреЛ рд╕рд╛рде рдЕрдиреБрд░реЛрдз, рдЬрд╕рдордзреНрдпреЗ рдкреНрд░рддреНрдпреЗрдХрд▓реЗ рдЙрддреНрдХреГрд╖реНрдЯ рдЙрджреНрджреЗрд╢реНрдпрдХрд╛ рд╕рд╛рде рдорд╛рддреНрд░ рдХрд╛рд░реНрдп рдЧрд░реЗрдХреЛ рдЫред

0: рдкреНрд░рдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдЪрд╛рд╣рдиреНрдереЗ?

PostgreSQL Antipatterns: рдирд╛рдорджреНрд╡рд╛рд░рд╛ рдЦреЛрдЬрдХреЛ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдкрд░рд┐рд╖реНрдХрд░рдгрдХреЛ рдХрдерд╛, рд╡рд╛ "рдЕрдкреНрдЯрд┐рдорд╛рдЗрдЬреЗрд╕рди рдЕрдЧрд╛рдбрд┐ рд░ рдкрдЫрд╛рдбрд┐"[KDPV рдпрд╣рд╛рдБ рджреЗрдЦрд┐]

рдкреНрд░рдпреЛрдЧрдХрд░реНрддрд╛рд▓реЗ рдирд╛рдорджреНрд╡рд╛рд░рд╛ "рдЫрд┐рдЯреЛ" рдЦреЛрдЬрдХреЛ рдмрд╛рд░реЗрдорд╛ рдХреБрд░рд╛ рдЧрд░реНрджрд╛ рд╕рд╛рдорд╛рдиреНрдпрддрдпрд╛ рдХреЗ рдорддрд▓рдм рд╣реБрдиреНрдЫ? рдпреЛ рд▓рдЧрднрдЧ рдХрд╣рд┐рд▓реНрдпреИ рдПрдХ substring рдХреЛ рд▓рд╛рдЧреА рдПрдХ "рдЗрдорд╛рдирджрд╛рд░" рдЦреЛрдЬ рд╣реБрди рдЬрд╛рдиреНрдЫ ... LIKE '%╤А╨╛╨╖╨░%' - рдХрд┐рдирднрдиреЗ рддреНрдпрд╕рдкрдЫрд┐ рдкрд░рд┐рдгрд╛рдо рдорд╛рддреНрд░ рд╕рдорд╛рд╡реЗрд╢ рдЫреИрди '╨а╨╛╨╖╨░╨╗╨╕╤П' ╨╕ '╨Ь╨░╨│╨░╨╖╨╕╨╜ ╨а╨╛╨╖╨░'рддрд░ '╨У╤А╨╛╨╖╨░' рд░ рдкрдирд┐ '╨Ф╨╛╨╝ ╨Ф╨╡╨┤╨░ ╨Ь╨╛╤А╨╛╨╖╨░'.

рдкреНрд░рдпреЛрдЧрдХрд░реНрддрд╛рд▓реЗ рджреИрдирд┐рдХ рд╕реНрддрд░рдорд╛ рдорд╛рдиреНрджрдЫ рдХрд┐ рддрдкрд╛рдЗрдБ рдЙрд╕рд▓рд╛рдИ рдкреНрд░рджрд╛рди рдЧрд░реНрдиреБрд╣реБрдиреЗрдЫ рд╢рдмреНрджрдХреЛ рд╕реБрд░реБрдорд╛ рдЦреЛрдЬреНрдиреБрд╣реЛрд╕реН рд╢реАрд░реНрд╖рдХрдорд╛ рд░ рдпрд╕рд▓рд╛рдИ рдЕрдЭ рд╕рд╛рдиреНрджрд░реНрднрд┐рдХ рдмрдирд╛рдЙрдиреБрд╣реЛрд╕реН рдорд╛ рд╕реБрд░реБ рд╣реБрдиреНрдЫ рдкреНрд░рд╡реЗрд╢ рдЧрд░реЗрдХреЛред рд░ рддрдкрд╛рдИрдВрд▓реЗ рдпреЛ рдЧрд░реНрдиреБрд╣реБрдиреЗрдЫ рд▓рдЧрднрдЧ рддреБрд░реБрдиреНрддреИ - рдЗрдиреНрдЯрд░рд▓рд╛рдЗрдирд░ рдЗрдирдкреБрдЯрдХреЛ рд▓рд╛рдЧрд┐ред

1: рдХрд╛рд░реНрдп рд╕реАрдорд┐рдд рдЧрд░реНрдиреБрд╣реЛрд╕реН

рд░ рдЕрдЭ рдмрдвреА, рдПрдХ рд╡реНрдпрдХреНрддрд┐ рд╡рд┐рд╢реЗрд╖ рд░реВрдкрдорд╛ рдкреНрд░рд╡реЗрд╢ рдЧрд░реНрджреИрди '╤А╨╛╨╖ ╨╝╨░╨│╨░╨╖', рддрд╛рдХрд┐ рддрдкрд╛рдИрдВрд▓реЗ рдЙрдкрд╕рд░реНрдЧ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рддреНрдпреЗрдХ рд╢рдмреНрдж рдЦреЛрдЬреНрдиреБ рдкрд░реНрдЫред рд╣реЛрдЗрди, рдкреНрд░рдпреЛрдЧрдХрд░реНрддрд╛рдХреЛ рд▓рд╛рдЧрд┐ рдЕрдиреНрддрд┐рдо рд╢рдмреНрджрдХреЛ рд▓рд╛рдЧрд┐ рджреНрд░реБрдд рд╕рдЩреНрдХреЗрддрдорд╛ рдЬрд╡рд╛рдл рджрд┐рдирдХреЛ рд▓рд╛рдЧрд┐ рдЕрдШрд┐рд▓реНрд▓реЛ рд╢рдмреНрджрд╣рд░реВрд▓рд╛рдИ рдЙрджреНрджреЗрд╢реНрдпрдкреВрд░реНрд╡рдХ "рдЕрдиреНрдбрд░рд╕реНрдкреЗрд╕рд┐рдлрд╛рдЗ" рдЧрд░реНрдиреБ рднрдиреНрджрд╛ рдзреЗрд░реИ рд╕рдЬрд┐рд▓реЛ рдЫ - рд╣реЗрд░реНрдиреБрд╣реЛрд╕реН рдХреБрдиреИ рдкрдирд┐ рдЦреЛрдЬ рдЗрдиреНрдЬрд┐рдирд▓реЗ рдпрд╕рд▓рд╛рдИ рдХрд╕рд░реА рд╣реНрдпрд╛рдиреНрдбрд▓ рдЧрд░реНрдЫред

рд╕рд╛рдорд╛рдиреНрдп рджрд╛рдпрд╛рдБ рд╕рдорд╕реНрдпрд╛рдХреЛ рд▓рд╛рдЧрд┐ рдЖрд╡рд╢реНрдпрдХрддрд╛рд╣рд░реВ рдирд┐рд░реНрдорд╛рдг рдЧрд░реНрдиреБ рдЖрдзрд╛ рднрдиреНрджрд╛ рдмрдвреА рд╕рдорд╛рдзрд╛рди рд╣реЛред рдХрд╣рд┐рд▓реЗрдХрд╛рд╣реАрдБ рд╕рд╛рд╡рдзрд╛рди рдкреНрд░рдпреЛрдЧ рдХреЗрд╕ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдирддрд┐рдЬрд╛рдорд╛ рдЙрд▓реНрд▓реЗрдЦрдиреАрдп рдкреНрд░рднрд╛рд╡ рдкрд╛рд░реНрди рд╕рдХреНрдЫ.

рдПрдХ рд╕рд╛рд░ рд╡рд┐рдХрд╛рд╕рдХрд░реНрддрд╛рд▓реЗ рдХреЗ рдЧрд░реНрдЫ?

1.0: рдмрд╛рд╣реНрдп рдЦреЛрдЬ рдЗрдиреНрдЬрд┐рди

рдУрд╣, рдЦреЛрдЬреА рдЧрд░реНрди рдЧрд╛рд╣реНрд░реЛ рдЫ, рдо рдХреЗрд╣рд┐ рдкрдирд┐ рдЧрд░реНрди рдЪрд╛рд╣рдиреНрди - рдпрд╕рд▓рд╛рдИ рдбреЗрднрдкреНрд╕рд▓рд╛рдИ рджрд┐рдФрдВ! рддрд┐рдиреАрд╣рд░реВрд▓рд╛рдИ рдбрд╛рдЯрд╛рдмреЗрд╕рдорд╛ рдмрд╛рд╣рд┐рд░реА рдЦреЛрдЬ рдЗрдиреНрдЬрд┐рди рдкреНрд░рдпреЛрдЧ рдЧрд░реНрди рджрд┐рдиреБрд╣реЛрд╕реН: Sphinx, ElasticSearch,...

рд╕рд┐рдВрдХреНрд░реЛрдирд╛рдЗрдЬреЗрд╕рди рд░ рдкрд░рд┐рд╡рд░реНрддрдирд╣рд░реВрдХреЛ рдЧрддрд┐рдХреЛ рд╕рдиреНрджрд░реНрднрдорд╛ рд╢реНрд░рдо-рдЧрд╣рди рднрдП рдкрдирд┐ рдХрд╛рдо рдЧрд░реНрдиреЗ рд╡рд┐рдХрд▓реНрдкред рддрд░ рд╣рд╛рдореНрд░реЛ рдЕрд╡рд╕реНрдерд╛рдорд╛ рд╣реЛрдЗрди, рдХрд┐рдирдХрд┐ рдЦреЛрдЬ рдкреНрд░рддреНрдпреЗрдХ рдЧреНрд░рд╛рд╣рдХрдХреЛ рд▓рд╛рдЧрд┐ рдорд╛рддреНрд░ рдЙрд╕рдХреЛ рдЦрд╛рддрд╛ рдбреЗрдЯрд╛рдХреЛ рдврд╛рдБрдЪрд╛ рднрд┐рддреНрд░ рдЧрд░рд┐рдиреНрдЫред рд░ рдбрд╛рдЯрд╛рдорд╛ рдПрдХрджрдо рдЙрдЪреНрдЪ рдкрд░рд┐рд╡рд░реНрддрдирд╢реАрд▓рддрд╛ рдЫ - рд░ рдпрджрд┐ рдкреНрд░рдмрдиреНрдзрдХрд▓реЗ рдЕрдм рдХрд╛рд░реНрдбрдорд╛ рдкреНрд░рд╡реЗрд╢ рдЧрд░реЗрдХреЛ рдЫ '╨Ь╨░╨│╨░╨╖╨╕╨╜ ╨а╨╛╨╖╨░', рддреНрдпрд╕рдкрдЫрд┐ 5-10 рд╕реЗрдХреЗрдиреНрдб рдкрдЫрд┐ рдЙрд╕рд▓реЗ рдкрд╣рд┐рд▓реЗ рдиреИ рдпрд╛рдж рдЧрд░реНрди рд╕рдХреНрдЫ рдХрд┐ рдЙрд╕рд▓реЗ рддреНрдпрд╣рд╛рдБ рдЖрдлреНрдиреЛ рдЗрдореЗрд▓ рд╕рдВрдХреЗрдд рдЧрд░реНрди рдмрд┐рд░реНрд╕реЗрдХреЛ рдЫ рд░ рдпрд╕рд▓рд╛рдИ рдлреЗрд▓рд╛ рдкрд╛рд░реНрди рд░ рдпрд╕рд▓рд╛рдИ рд╕рдЪреНрдпрд╛рдЙрди рдЪрд╛рд╣рдиреНрдЫреБред

рддреНрдпрд╕реИрд▓реЗ - рдЖрдЙрдиреБрд╣реЛрд╕реН "рдбрд╛рдЯрд╛рдмреЗрд╕рдорд╛ рд╕реАрдзрд╛" рдЦреЛрдЬреНрдиреБрд╣реЛрд╕реНред рд╕реМрднрд╛рдЧреНрдп рджреЗрдЦрд┐, PostgreSQL рд▓реЗ рд╣рд╛рдореАрд▓рд╛рдИ рдпреЛ рдЧрд░реНрди рдЕрдиреБрдорддрд┐ рджрд┐рдиреНрдЫ, рд░ рдХреЗрд╡рд▓ рдПрдХ рд╡рд┐рдХрд▓реНрдк рд╣реЛрдЗрди - рд╣рд╛рдореА рддрд┐рдиреАрд╣рд░реВрд▓рд╛рдИ рд╣реЗрд░реНрдиреЗрдЫреМрдВред

рез.рез: "рдЗрдорд╛рдирджрд╛рд░" рд╕рдмрд╕реНрдЯреНрд░рд┐рдЩ

рд╣рд╛рдореА "рд╕рдмрд╕реНрдЯреНрд░рд┐рдВрдЧ" рд╢рдмреНрджрдорд╛ рдЯрд╛рдБрд╕рд┐рдиреНрдЫреМрдВред рддрд░ рд╕рдмрд╕реНрдЯреНрд░рд┐рдВрдЧ рджреНрд╡рд╛рд░рд╛ рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рдЦреЛрдЬрдХреЛ рд▓рд╛рдЧрд┐ (рд░ рдирд┐рдпрдорд┐рдд рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐рд╣рд░реВ рдкрдирд┐!) рддреНрдпрд╣рд╛рдБ рдЙрддреНрдХреГрд╖реНрдЯ рдЫ рдореЛрдбреНрдпреБрд▓ 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: рдирд╛рдорджреНрд╡рд╛рд░рд╛ рдЦреЛрдЬрдХреЛ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдкрд░рд┐рд╖реНрдХрд░рдгрдХреЛ рдХрдерд╛, рд╡рд╛ "рдЕрдкреНрдЯрд┐рдорд╛рдЗрдЬреЗрд╕рди рдЕрдЧрд╛рдбрд┐ рд░ рдкрдЫрд╛рдбрд┐"
[explan.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: рдирд╛рдорджреНрд╡рд╛рд░рд╛ рдЦреЛрдЬрдХреЛ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдкрд░рд┐рд╖реНрдХрд░рдгрдХреЛ рдХрдерд╛, рд╡рд╛ "рдЕрдкреНрдЯрд┐рдорд╛рдЗрдЬреЗрд╕рди рдЕрдЧрд╛рдбрд┐ рд░ рдкрдЫрд╛рдбрд┐"
[explan.tensor.ru рдорд╛ рд╣реЗрд░реНрдиреБрд╣реЛрд╕реН]

рдпрд╣рд╛рдБ рдХреНрд╡реЗрд░реА рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрдирдХреЛ рд╕рдорд╛рдирд╛рдиреНрддрд░рд▓реЗ рд╣рд╛рдореАрд▓рд╛рдИ рдереЛрд░реИ рдорджреНрджрдд рдЧрд░реНтАНрдпреЛ, рд╕рдордпрд▓рд╛рдИ рдЖрдзрд╛рдорд╛ рдХрд╛рдЯреЗрд░ 11msред рд░ рд╣рд╛рдореА 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: рдирд╛рдорджреНрд╡рд╛рд░рд╛ рдЦреЛрдЬрдХреЛ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдкрд░рд┐рд╖реНрдХрд░рдгрдХреЛ рдХрдерд╛, рд╡рд╛ "рдЕрдкреНрдЯрд┐рдорд╛рдЗрдЬреЗрд╕рди рдЕрдЧрд╛рдбрд┐ рд░ рдкрдЫрд╛рдбрд┐"
[explan.tensor.ru рдорд╛ рд╣реЗрд░реНрдиреБрд╣реЛрд╕реН]

рдЙрддреНрдХреГрд╖реНрдЯ рдкреНрд░рджрд░реНрд╢рди - рдХреБрд▓ 0.05ms рд░ 100KB рднрдиреНрджрд╛ рдЕрд▓рд┐ рдмрдвреА рдкрдвреНрдиреБрд╣реЛрд╕реН! рд╣рд╛рдореАрд▓реЗ рдорд╛рддреНрд░ рдмрд┐рд░реНрд╕рд┐рдпреМрдВ рдирд╛рдо рджреНрд╡рд╛рд░рд╛ рдХреНрд░рдордмрджреНрдз рдЧрд░реНрдиреБрд╣реЛрд╕реНрддрд╛рдХрд┐ рдкреНрд░рдпреЛрдЧрдХрд░реНрддрд╛ рдкрд░рд┐рдгрд╛рдорд╣рд░реВрдорд╛ рд╣рд░рд╛рдЙрди рдирдкрд░реЛрд╕реН:

SELECT
  *
FROM
  firms
WHERE
  lower(name) LIKE ('╤А╨╛╨╖╨░' || '%')
ORDER BY
  lower(name)
LIMIT 10;

PostgreSQL Antipatterns: рдирд╛рдорджреНрд╡рд╛рд░рд╛ рдЦреЛрдЬрдХреЛ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдкрд░рд┐рд╖реНрдХрд░рдгрдХреЛ рдХрдерд╛, рд╡рд╛ "рдЕрдкреНрдЯрд┐рдорд╛рдЗрдЬреЗрд╕рди рдЕрдЧрд╛рдбрд┐ рд░ рдкрдЫрд╛рдбрд┐"
[explan.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: рдирд╛рдорджреНрд╡рд╛рд░рд╛ рдЦреЛрдЬрдХреЛ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдкрд░рд┐рд╖реНрдХрд░рдгрдХреЛ рдХрдерд╛, рд╡рд╛ "рдЕрдкреНрдЯрд┐рдорд╛рдЗрдЬреЗрд╕рди рдЕрдЧрд╛рдбрд┐ рд░ рдкрдЫрд╛рдбрд┐"
[explan.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 рд░ gin рджреБрд╡реИ рдЫ, рддрд░ рд╕рд╛рдВрдЦреНрдпрд┐рдХреАрдп рд░реВрдкрдорд╛ рдпреЛ рдмрд╛рд╣рд┐рд░ рдЬрд╛рдиреНрдЫ рдХрд┐ 10% рднрдиреНрджрд╛ рдХрдо рдЕрдиреБрд░реЛрдзрд╣рд░реВ рджреЛрд╕реНрд░реЛ рдмреНрд▓рдХрдХреЛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрдирдорд╛ рдкреБрдЧреНрдЫрдиреНред рддреНрдпреЛ рд╣реЛ, рдХрд╛рд░реНрдпрдХреЛ рд▓рд╛рдЧрд┐ рдЕрдЧреНрд░рд┐рдо рдЬреНрдЮрд╛рдд рдпрд╕реНрддреЛ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕реАрдорд┐рддрддрд╛рд╣рд░реВрдХреЛ рд╕рд╛рде, рд╣рд╛рдореА рд▓рдЧрднрдЧ рдПрдХ рд╣рдЬрд╛рд░ рдкрдЯрдХ рд╕рд░реНрднрд░ рд╕реНрд░реЛрддрд╣рд░реВрдХреЛ рдХреБрд▓ рдЦрдкрдд рдШрдЯрд╛рдЙрди рд╕рдХреНрд╖рдо рднрдпреМрдВ!

1.5*: рд╣рд╛рдореА рдлрд╛рдЗрд▓ рдмрд┐рдирд╛ рдЧрд░реНрди рд╕рдХреНрдЫреМрдВ

рдорд╛рдерд┐ LIKE рд╣рд╛рдореАрд▓рд╛рдИ рдЧрд▓рдд рдХреНрд░рдордмрджреНрдз рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдирдмрд╛рдЯ рд░реЛрдХрд┐рдПрдХреЛ рдерд┐рдпреЛред рддрд░ рдпрд╕рд▓рд╛рдИ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдиреЗ рдЕрдкрд░реЗрдЯрд░ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдЧрд░реЗрд░ "рд╕рд╣реА рдорд╛рд░реНрдЧрдорд╛ рд╕реЗрдЯ" рдЧрд░реНрди рд╕рдХрд┐рдиреНрдЫ:

рдкреВрд░реНрд╡рдирд┐рд░реНрдзрд╛рд░рд┐рдд рд░реВрдкрдорд╛ рдпреЛ рдорд╛рдирд┐рдиреНрдЫ ASCред рдердк рд░реВрдкрдорд╛, рддрдкрд╛рдЗрдБ рдХреНрд▓рдЬрдорд╛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХреНрд░рдордмрджреНрдз рдЕрдкрд░реЗрдЯрд░рдХреЛ рдирд╛рдо рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдЧрд░реНрди рд╕рдХреНрдиреБрд╣реБрдиреНрдЫ USINGред рдХреНрд░рдордмрджреНрдз рдЕрдкрд░реЗрдЯрд░ рдмреА-рдЯреНрд░реА рдЕрдкрд░реЗрдЯрд░рд╣рд░реВрдХреЛ рдХреЗрд╣реА рдкрд░рд┐рд╡рд╛рд░рдХреЛ рднрдиреНрджрд╛ рдХрдо рд╡рд╛ рдмрдвреАрдХреЛ рд╕рджрд╕реНрдп рд╣реБрдиреБрдкрд░реНрдЫред ASC рд╕рд╛рдорд╛рдиреНрдпрддрдпрд╛ рдмрд░рд╛рдмрд░ USING < ╨╕ DESC рд╕рд╛рдорд╛рдиреНрдпрддрдпрд╛ рдмрд░рд╛рдмрд░ USING >.

рд╣рд╛рдореНрд░реЛ рдорд╛рдорд▓рд╛ рдорд╛, "рдХрдо" рдЫ ~<~:

SELECT
  *
FROM
  firms
WHERE
  lower(name) LIKE ('╤А╨╛╨╖╨░' || '%')
ORDER BY
  lower(name) USING ~<~
LIMIT 10;

PostgreSQL Antipatterns: рдирд╛рдорджреНрд╡рд╛рд░рд╛ рдЦреЛрдЬрдХреЛ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдкрд░рд┐рд╖реНрдХрд░рдгрдХреЛ рдХрдерд╛, рд╡рд╛ "рдЕрдкреНрдЯрд┐рдорд╛рдЗрдЬреЗрд╕рди рдЕрдЧрд╛рдбрд┐ рд░ рдкрдЫрд╛рдбрд┐"
[explan.tensor.ru рдорд╛ рд╣реЗрд░реНрдиреБрд╣реЛрд╕реН]

2: рдХрд╕рд░реА рдЕрдиреБрд░реЛрдзрд╣рд░реВ рдЦрдЯреНрдЯрд╛ рд╣реБрдиреНрдЫрдиреН

рдЕрдм рд╣рд╛рдореА рд╣рд╛рдореНрд░реЛ рдЕрдиреБрд░реЛрдзрд▓рд╛рдИ рдЫ рдорд╣рд┐рдирд╛ рд╡рд╛ рдПрдХ рд╡рд░реНрд╖рдХреЛ рд▓рд╛рдЧрд┐ "рд╕рд┐рдорд░" рдЧрд░реНрди рдЫреЛрдбреНрдЫреМрдВ, рд░ рдореЗрдореЛрд░реАрдХреЛ рдХреБрд▓ рджреИрдирд┐рдХ "рдкрдореНрдкрд┐рдЩ" рдХреЛ рд╕реВрдЪрдХрд╣рд░реВрдХреЛ рд╕рд╛рде рдлреЗрд░рд┐ "рд╢реАрд░реНрд╖рдорд╛" рдлреЗрд▓рд╛ рдкрд╛рд░реНрди рдкрд╛рдЙрдБрджрд╛ рд╣рд╛рдореА рдЫрдХреНрдХ рдкрд░реНрдЫреМрдВредрдмрдлрд░ рд╕рд╛рдЭрд╛ рд╣рд┐рдЯ) рдорд╛ 5.5TB - рдЕрд░реНрдерд╛рддреН, рдпреЛ рдкрд╣рд┐рд▓реЗ рднрдиреНрджрд╛ рдмрдвреА рдерд┐рдпреЛред

рд╣реЛрдЗрди, рдирд┐рд╕реНрд╕рдиреНрджреЗрд╣, рд╣рд╛рдореНрд░реЛ рд╡реНрдпрд╛рдкрд╛рд░ рдмрдвреЗрдХреЛ рдЫ рд░ рд╣рд╛рдореНрд░реЛ рдХрд╛рд░реНрдпрднрд╛рд░ рдмрдвреЗрдХреЛ рдЫ, рддрд░ рдЙрд╣реА рд░рдХрдорд▓реЗ рд╣реЛрдЗрди! рдпрд╕рдХреЛ рдорддрд▓рдм рдпрд╣рд╛рдБ рдХреЗрд╣рд┐ рдорд╛рдЫрд╛ рдЫ - рдпрд╕рд▓рд╛рдИ рдмрд╛рд╣рд┐рд░ рдирд┐рдХрд╛рд▓реМрдВред

реи.рез: рдкреЗрдЬрд┐рдЩрдХреЛ рдЬрдиреНрдо

рдХреЗрд╣рд┐ рдмрд┐рдиреНрджреБрдорд╛, рдЕрд░реНрдХреЛ рд╡рд┐рдХрд╛рд╕ рдЯреЛрд▓реАрд▓реЗ рджреНрд░реБрдд рд╕рдмрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЦреЛрдЬрдмрд╛рдЯ рд░рдЬрд┐рд╕реНрдЯреНрд░реАрдорд╛ рдЙрд╣реА, рддрд░ рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рдкрд░рд┐рдгрд╛рдорд╣рд░реВ "рдЬрдореНрдк" рдЧрд░реНрди рд╕рдореНрднрд╡ рдмрдирд╛рдЙрди рдЪрд╛рд╣рдиреНрдереЗред рдкреГрд╖реНрда рдиреЗрднрд┐рдЧреЗрд╕рди рдмрд┐рдирд╛ рд░рдЬрд┐рд╕реНрдЯреНрд░реА рдХреЗ рд╣реЛ? рдпрд╕рд▓рд╛рдИ рдмрд┐рдЧрд╛рд░реМрдВ!

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

рддреНрдпреЛ рд╣реЛ, рдпреЛ рд╕реНрдкрд╖реНрдЯ рдЫ рдХрд┐ рдкрд░рд┐рдгрд╛рдо, рдЕрдиреНрддрдорд╛, рдареНрдпрд╛рдХреНрдХреИ рдЙрд╕реНрддреИ рдЫ, рддрд░ 2nd CTE рд╕рдмрдХреНрд╡реЗрд░реАрдорд╛ "рдЙрдбрд╛рди" рдХреЛ рд╕рдВрднрд╛рд╡рдирд╛ рдзреЗрд░реИ рдЙрдЪреНрдЪ рднрдПрдХреЛ рдЫ, рд░ рдпреЛ рдмрд┐рдирд╛ рдкрдирд┐, рд╕реНрдкрд╖реНрдЯ рд░реВрдкрдорд╛ рдЕрдзрд┐рдХ рдкрдардиреАрдп.

рддрд░ рдпреЛ рд╕рдмреИрднрдиреНрджрд╛ рджреБрдЦрдж рдХреБрд░рд╛ рд╣реЛрдЗрдиред рд╡рд┐рдХрд╛рд╕рдХрд░реНрддрд╛рд▓реЗ рдЪрдпрди рдЧрд░реНрди рднрдиреЗрдкрдЫрд┐ DISTINCT рд╡рд┐рд╢реЗрд╖рдХрд╛ рд▓рд╛рдЧрд┐ рд╣реЛрдЗрди, рддрд░ рдПрдХреИ рдкрдЯрдХ рд╕рдмреИ рдХреНрд╖реЗрддреНрд░рд╣рд░реВрдХреЛ рд▓рд╛рдЧрд┐ рд░реЗрдХрд░реНрдбрд╣рд░реВ, рддреНрдпрд╕рдкрдЫрд┐ sub_query рдлрд┐рд▓реНрдб тАФ рд╕рдмрдХреНрд╡реЗрд░реАрдХреЛ рдирддрд┐рдЬрд╛ тАФ рддреНрдпрд╣рд╛рдБ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдкрдорд╛ рд╕рдорд╛рд╡реЗрд╢ рдЧрд░рд┐рдПрдХреЛ рдерд┐рдпреЛред рдЕрдм, рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЧрд░реНрди DISTINCT, рдбрд╛рдЯрд╛рдмреЗрд╕ рдкрд╣рд┐рд▓реЗ рдиреИ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЧрд░реНрди рдерд┐рдпреЛ 10 subqueries рд╣реЛрдЗрди, рддрд░ рд╕рдмреИ <2 * N> + 10!

2.4: рд╕рдмреИ рднрдиреНрджрд╛ рдорд╛рдерд┐ рд╕рд╣рдпреЛрдЧ!

рддреНрдпрд╕реЛрднрдП, рд╡рд┐рдХрд╛рд╕рдХрд░реНрддрд╛рд╣рд░реВ рдмрд╛рдБрдЪрд┐рд░рд╣реЗрдХрд╛ рдерд┐рдП - рдЙрдиреАрд╣рд░реВрд▓реЗ рдЪрд┐рдиреНрддрд╛ рдЧрд░реЗрдирдиреН, рдХрд┐рдирднрдиреЗ рдкреНрд░рдпреЛрдЧрдХрд░реНрддрд╛рд╕рдБрдЧ рд╕реНрдкрд╖реНрдЯ рд░реВрдкрдорд╛ рдкреНрд░рддреНрдпреЗрдХ рдкрдЫрд┐рдХреЛ "рдкреГрд╖реНрда" рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрдирдХреЛ рд▓рд╛рдЧрд┐ рдкреБрд░рд╛рдиреЛ рдордиреНрджреАрдХреЛ рд╕рд╛рде рдорд╣рддреНрддреНрд╡рдкреВрд░реНрдг N рдорд╛рдирд╣рд░реВрдорд╛ рд░рдЬрд┐рд╕реНрдЯреНрд░реАрд▓рд╛рдИ "рд╕рдорд╛рдпреЛрдЬрд┐рдд" рдЧрд░реНрди рдкрд░реНрдпрд╛рдкреНрдд рдзреИрд░реНрдп рдерд┐рдПрдиред

рдЬрдмрд╕рдореНрдо рдЕрд░реНрдХреЛ рд╡рд┐рднрд╛рдЧрдмрд╛рдЯ рд╡рд┐рдХрд╛рд╕рдХрд░реНрддрд╛рд╣рд░реВ рдЖрдП рд░ рдпрд╕реНрддреЛ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╡рд┐рдзрд┐ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрди рдЪрд╛рд╣рдиреНрдереЗ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдЦреЛрдЬрдХреЛ рд▓рд╛рдЧрд┐ - рддреНрдпреЛ рд╣реЛ, рд╣рд╛рдореА рдХреЗрд╣рд┐ рдирдореВрдирд╛рдмрд╛рдЯ рдПрдХ рдЯреБрдХреНрд░рд╛ рд▓рд┐рдиреНрдЫреМрдВ, рдпрд╕рд▓рд╛рдИ рдердк рд╕рд░реНрддрд╣рд░реВрджреНрд╡рд╛рд░рд╛ рдлрд┐рд▓реНрдЯрд░ рдЧрд░реНрдЫреМрдВ, рдирддрд┐рдЬрд╛ рдХреЛрд░реНрдЫреМрдВ, рддреНрдпрд╕рдкрдЫрд┐ рдЕрд░реНрдХреЛ рдЯреБрдХреНрд░рд╛ (рдЬреБрди рд╣рд╛рдореНрд░реЛ рдХреЗрд╕рдорд╛ N рдмрдврд╛рдПрд░ рдкреНрд░рд╛рдкреНрдд рд╣реБрдиреНрдЫ), рд░ рд╣рд╛рдореАрд▓реЗ рд╕реНрдХреНрд░рд┐рди рднрд░реНрджрд╛рд╕рдореНрдоред

рд╕рд╛рдорд╛рдиреНрдпрддрдпрд╛, рд╕рдорд╛рддрд┐рдПрдХреЛ рдирдореВрдирд╛рдорд╛ N рд▓рдЧрднрдЧ 17K рдХреЛ рдорд╛рди рдкреБрдЧреНрдпреЛ, рд░ рдХреЗрд╡рд▓ рдПрдХ рджрд┐рдирдорд╛ рдХрдореНрддрд┐рдорд╛ 4K рдпрд╕реНрддрд╛ рдЕрдиреБрд░реЛрдзрд╣рд░реВ "рдЪреЗрдирдХреЛ рд╕рд╛рде" рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЧрд░рд┐рдпреЛред рддрд┐рдиреАрд╣рд░реВрдордзреНрдпреЗ рдЕрдиреНрддрд┐рдорд▓рд╛рдИ рд╕рд╛рд╣рд╕рдкреВрд░реНрд╡рдХ рд╕реНрдХреНрдпрд╛рди рдЧрд░рд┐рдПрдХреЛ рдерд┐рдпреЛ рдкреНрд░рддрд┐ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ 1GB рдореЗрдореЛрд░реА...

рдХреБрд▓

PostgreSQL Antipatterns: рдирд╛рдорджреНрд╡рд╛рд░рд╛ рдЦреЛрдЬрдХреЛ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдкрд░рд┐рд╖реНрдХрд░рдгрдХреЛ рдХрдерд╛, рд╡рд╛ "рдЕрдкреНрдЯрд┐рдорд╛рдЗрдЬреЗрд╕рди рдЕрдЧрд╛рдбрд┐ рд░ рдкрдЫрд╛рдбрд┐"

рд╕реНрд░реЛрдд: www.habr.com

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдердкреНрди