SQL HowTo: рдХреНрд╡реЗрд░реАрдордзреНрдпреЗ рдереЗрдЯ рдПрдХ while-loop рд▓рд┐рд╣рд╛, рдХрд┐рдВрд╡рд╛ "Elementary three-way"

рд╡реЗрд│реЛрд╡реЗрд│реА, рдХрд│рд╛рдВрдЪреНрдпрд╛ рд╕рдВрдЪрд╛рджреНрд╡рд╛рд░реЗ рд╕рдВрдмрдВрдзрд┐рдд рдбреЗрдЯрд╛ рд╢реЛрдзрдгреНрдпрд╛рдЪреЗ рдХрд╛рдо рдЙрджреНрднрд╡рддреЗ, рдЬреЛрдкрд░реНрдпрдВрдд рдЖрдкрдг рдЖрд╡рд╢реНрдпрдХ рдЕрд╕рд▓реЗрд▓реНрдпрд╛ рдПрдХреВрдг рдиреЛрдВрджреАрдВрдЪреА рд╕рдВрдЦреНрдпрд╛ рдЧрд╛рдардд рдирд╛рд╣реА рддреЛрдкрд░реНрдпрдВрдд.

рд╕рд░реНрд╡рд╛рдд "рд╡рд╛рд╕реНрддрд╡рд┐рдХ" рдЙрджрд╛рд╣рд░рдг рдореНрд╣рдгрдЬреЗ рдирд┐рд╖реНрдХрд░реНрд╖ рдХрд╛рдврдгреЗ реиреж рд╕рд░реНрд╡рд╛рдд рдЬреБрдиреА рдХрд╛рдореЗ, рд╕реВрдЪреАрдмрджреНрдз рдХрд░реНрдордЪрд╛рд▒реНрдпрд╛рдВрдЪреНрдпрд╛ рдпрд╛рджреАрдд (рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, рдПрдХрд╛рдЪ рд╡рд┐рднрд╛рдЧрд╛рдд). рдХрд╛рд░реНрдпрдХреНрд╖реЗрддреНрд░рд╛рдВрдЪрд╛ рдереЛрдбрдХреНрдпрд╛рдд рд╕рд╛рд░рд╛рдВрд╢ рдЕрд╕рд▓реЗрд▓реНрдпрд╛ рд╡рд┐рд╡рд┐рдз рд╡реНрдпрд╡рд╕реНрдерд╛рдкрди рдбреЕрд╢рдмреЛрд░реНрдбрд╕рд╛рдареА, рдмрд╣реБрддреЗрдХрджрд╛ рд╕рдорд╛рди рдереАрдо рдЖрд╡рд╢реНрдпрдХ рдЕрд╕рддреЗ.

SQL HowTo: рдХреНрд╡реЗрд░реАрдордзреНрдпреЗ рдереЗрдЯ рдПрдХ while-loop рд▓рд┐рд╣рд╛, рдХрд┐рдВрд╡рд╛ "Elementary three-way"

рдпрд╛ рд▓реЗрдЦрд╛рдд, рдЖрдкрдг PostgreSQL рдордзреНрдпреЗ рдпрд╛ рд╕рдорд╕реНрдпреЗрд╡рд░ "рднреЛрд│реЗ" рдЙрдкрд╛рдп рд▓рд╛рдЧреВ рдХрд░рдгреНрдпрд╛рдЪрд╛ рд╡рд┐рдЪрд╛рд░ рдХрд░реВ, рдЬреЛ "рдЕрдзрд┐рдХ рд╕реНрдорд╛рд░реНрдЯ" рдЖрдгрд┐ рдЕрддрд┐рд╢рдп рдЬрдЯрд┐рд▓ рдЕрд▓реНрдЧреЛрд░рд┐рдердо рдЖрд╣реЗ. рд╕рд╛рдкрдбрд▓реЗрд▓реНрдпрд╛ рдбреЗрдЯрд╛рд╡рд░ рдЖрдзрд╛рд░рд┐рдд рдПрдХреНрдЭрд┐рдЯ рдХрдВрдбрд┐рд╢рдирд╕рд╣ SQL рдордзреНрдпреЗ "рд▓реВрдк"., рдЬреЗ рд╕рд╛рдорд╛рдиреНрдп рд╡рд┐рдХрд╛рд╕рд╛рд╕рд╛рдареА рдЖрдгрд┐ рдЗрддрд░ рддрддреНрд╕рдо рдкреНрд░рдХрд░рдгрд╛рдВрдордзреНрдпреЗ рд╡рд╛рдкрд░рдгреНрдпрд╛рд╕рд╛рдареА рдЙрдкрдпреБрдХреНрдд рдард░реВ рд╢рдХрддреЗ.

рдЪрд▓рд╛ рдПрдХ рдЪрд╛рдЪрдгреА рдбреЗрдЯрд╛ рд╕реЗрдЯ рдШреЗрдКрдпрд╛ рдорд╛рдЧреАрд▓ рд▓реЗрдЦрдХреНрд░рдорд╡рд╛рд░реА рд▓рд╛рд╡рд▓реЗрд▓реНрдпрд╛ рдореВрд▓реНрдпрд╛рдВрд╢реА рдЬреБрд│рддрд╛рдирд╛ рдЖрдЙрдЯрдкреБрдЯ рд░реЗрдХреЙрд░реНрдб рдПрдХрд╛ рд╡реЗрд│реЗрдкрд╛рд╕реВрди рджреБрд╕рд▒реНрдпрд╛ рд╡реЗрд│реА "рдЙрдбреА рдорд╛рд░рдгреНрдпрд╛рдкрд╛рд╕реВрди" рд░реЛрдЦрдгреНрдпрд╛рд╕рд╛рдареА, рдЪрд▓рд╛ рдкреНрд░рд╛рдердорд┐рдХ рдХреА рдЬреЛрдбреВрди рд╡рд┐рд╖рдп рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рд╡рд╛рдврд╡реВрдпрд╛.рд╣реЗ рддрд╛рдмрдбрддреЛрдм рддреЗ рдЕрджреНрд╡рд┐рддреАрдп рдмрдирд╡реЗрд▓ рдЖрдгрд┐ рд╕реНрдкрд╖реНрдЯ рдХреНрд░рдорд╡рд╛рд░реАрдЪреА рд╣рдореА рджреЗрдИрд▓:

CREATE INDEX ON task(owner_id, task_date, id);
-- ╨░ ╤Б╤В╨░╤А╤Л╨╣ - ╤Г╨┤╨░╨╗╨╕╨╝
DROP INDEX task_owner_id_task_date_idx;

рддреЗ рдЬрд╕реЗ рд╡рд╛рдЯрддреЗ рддрд╕реЗ рд▓рд┐рд╣рд┐рд▓реЗ рдЖрд╣реЗ.

рдкреНрд░рдердо, рд╡рд┐рдирдВрддреАрдЪреА рд╕рд░реНрд╡рд╛рдд рд╕реЛрдкреА рдЖрд╡реГрддреНрддреА рд░реЗрдЦрд╛рдЯреВрдпрд╛, рдХрд▓рд╛рдХрд╛рд░рд╛рдВрдЪреЗ рдЖрдпрдбреА рдкрд╛рд╕ рдХрд░реВрдпрд╛. рдЗрдирдкреБрдЯ рдкреЕрд░рд╛рдореАрдЯрд░ рдореНрд╣рдгреВрди рдЕтАНреЕрд░реЗ:

SELECT
  *
FROM
  task
WHERE
  owner_id = ANY('{1,2,4,8,16,32,64,128,256,512}'::integer[])
ORDER BY
  task_date, id
LIMIT 20;

SQL HowTo: рдХреНрд╡реЗрд░реАрдордзреНрдпреЗ рдереЗрдЯ рдПрдХ while-loop рд▓рд┐рд╣рд╛, рдХрд┐рдВрд╡рд╛ "Elementary three-way"
[explain.tensor.ru рдкрд╣рд╛]

рд╣реЗ рдереЛрдбреЗ рджреБрдГрдЦрдж рдЖрд╣реЗ - рдЖрдореНрд╣реА рдлрдХреНрдд реиреж рд░реЗрдХреЙрд░реНрдб рдСрд░реНрдбрд░ рдХреЗрд▓реЗ рдЖрдгрд┐ рдЗрдВрдбреЗрдХреНрд╕ рд╕реНрдХреЕрдирдиреЗ рддреЗ рдЖрдореНрд╣рд╛рд▓рд╛ рдкрд░рдд рдХреЗрд▓реЗ. репремреж рдУрд│реА, рдЬреЗ рдирдВрддрд░ рдХреНрд░рдорд╡рд╛рд░реА рд▓рд╛рд╡рд╛рд╡реЗ рд▓рд╛рдЧрд▓реЗ... рдЪрд▓рд╛ рдХрдореА рд╡рд╛рдЪрдгреНрдпрд╛рдЪрд╛ рдкреНрд░рдпрддреНрди рдХрд░реВрдпрд╛.

рдЕрдирдиреЗрд╕реНрдЯ + рдЕтАНреЕрд░реЗ

рдЖрдкрд▓реНрдпрд╛рд▓рд╛ рдорджрдд рдХрд░рдгрд╛рд░рд╛ рдкрд╣рд┐рд▓рд╛ рд╡рд┐рдЪрд╛рд░ рдореНрд╣рдгрдЬреЗ рдЖрдкрд▓реНрдпрд╛рд▓рд╛ рдЧрд░рдЬ рдЖрд╣реЗ рдХрд╛ рдлрдХреНрдд реиреж рдХреНрд░рдорд╡рд╛рд░реА рд▓рд╛рд╡рд▓реА рд░реЗрдХреЙрд░реНрдб, рдирдВрддрд░ рддреЗ рд╡рд╛рдЪрдгреНрдпрд╛рд╕рд╛рдареА рдкреБрд░реЗрд╕реЗ рдЖрд╣реЗ рдкреНрд░рддреНрдпреЗрдХрд╛рд╕рд╛рдареА рдПрдХрд╛рдЪ рдХреНрд░рдорд╛рдиреЗ реиреж рдкреЗрдХреНрд╖рд╛ рдЬрд╛рд╕реНрдд рдирд╛рд╣реА. рдХреА. рд╕реБрджреИрд╡рд╛рдиреЗ, рдпреЛрдЧреНрдп рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ (рдорд╛рд▓рдХ_рдЖрдпрдбреА, рдХрд╛рд░реНрдп_рддрд╛рд░реАрдЦ, рдЖрдпрдбреА) рдЖрдордЪреНрдпрд╛рдХрдбреЗ рдЖрд╣реЗ.

рдЪрд▓рд╛ рдХрд╛рдврдгреНрдпрд╛рдЪреА рдЖрдгрд┐ "рд╕реНрддрдВрднрд╛рдВрдордзреНрдпреЗ рдЙрд▓рдЧрдбрдгреНрдпрд╛рдЪреА" рд╕рдорд╛рди рдпрдВрддреНрд░рдгрд╛ рд╡рд╛рдкрд░реВрдпрд╛. рдЗрдВрдЯрд┐рдЧреНрд░рд▓ рдЯреЗрдмрд▓ рдПрдВрдЯреНрд░реА, рдЬрд╕реЗ рдХреА рд╢реЗрд╡рдЯрдЪрд╛ рд▓реЗрдЦ. рдЖрдкрдг рдлрдВрдХреНрд╢рди рд╡рд╛рдкрд░реВрди рдЕтАНреЕрд░реЗрдордзреНрдпреЗ рдлреЛрд▓реНрдбрд┐рдВрдЧ рджреЗрдЦреАрд▓ рд▓рд╛рдЧреВ рдХрд░реВ. ARRAY():

WITH T AS (
  SELECT
    unnest(ARRAY(
      SELECT
        t
      FROM
        task t
      WHERE
        owner_id = unnest
      ORDER BY
        task_date, id
      LIMIT 20 -- ╨╛╨│╤А╨░╨╜╨╕╤З╨╕╨▓╨░╨╡╨╝ ╤В╤Г╤В...
    )) r
  FROM
    unnest('{1,2,4,8,16,32,64,128,256,512}'::integer[])
)
SELECT
  (r).*
FROM
  T
ORDER BY
  (r).task_date, (r).id
LIMIT 20; -- ... ╨╕ ╤В╤Г╤В - ╤В╨╛╨╢╨╡

SQL HowTo: рдХреНрд╡реЗрд░реАрдордзреНрдпреЗ рдереЗрдЯ рдПрдХ while-loop рд▓рд┐рд╣рд╛, рдХрд┐рдВрд╡рд╛ "Elementary three-way"
[explain.tensor.ru рдкрд╣рд╛]

рдЕрд░реЗ, рддреЗ рддрд░ рдЦреВрдкрдЪ рдЪрд╛рдВрдЧрд▓реЗ рдЖрд╣реЗ! рекреж% рдЬрд▓рдж рдЖрдгрд┐ рек.рел рдкрдЯ рдХрдореА рдбреЗрдЯрд╛ рдорд▓рд╛ рддреЗ рд╡рд╛рдЪрд╛рд╡реЗ рд▓рд╛рдЧрд▓реЗ.

CTE рджреНрд╡рд╛рд░реЗ рдЯреЗрдмрд▓ рд░реЗрдХреЙрд░реНрдбрдЪреЗ рднреМрддрд┐рдХреАрдХрд░рдгрдореА рддреБрдордЪреЗ рд▓рдХреНрд╖ рдпрд╛ рд╡рд╕реНрддреБрд╕реНрдерд┐рддреАрдХрдбреЗ рд╡реЗрдзреВ рдЗрдЪреНрдЫрд┐рддреЛ рдХреА рдХрд╛рд╣реА рдмрд╛рдмрддреАрдд рд╕рдмрдХреНрд╡реЗрд░реАрдордзреНрдпреЗ рд░реЗрдХреЙрд░реНрдб рдлреАрд▓реНрдб рд╢реЛрдзрд▓реНрдпрд╛рдирдВрддрд░, рддреЗ CTE рдордзреНрдпреЗ "рд░реЕрдкрд┐рдВрдЧ" рди рдХрд░рддрд╛ рд▓рдЧреЗрдЪ рддреНрдпрд╛рд╡рд░ рдХрд╛рдо рдХрд░рдгреНрдпрд╛рдЪрд╛ рдкреНрд░рдпрддреНрди рдХреЗрд▓реНрдпрд╛рд╕, InitPlan рдЪреЗ "рдЧреБрдгрд╛рдХрд╛рд░" рдпрд╛ рд╕рдорд╛рди рдлреАрд▓реНрдбрдЪреНрдпрд╛ рд╕рдВрдЦреНрдпреЗрдЪреНрдпрд╛ рдкреНрд░рдорд╛рдгрд╛рдд:

SELECT
  ((
    SELECT
      t
    FROM
      task t
    WHERE
      owner_id = 1
    ORDER BY
      task_date, id
    LIMIT 1
  ).*);

Result  (cost=4.77..4.78 rows=1 width=16) (actual time=0.063..0.063 rows=1 loops=1)
  Buffers: shared hit=16
  InitPlan 1 (returns $0)
    ->  Limit  (cost=0.42..1.19 rows=1 width=48) (actual time=0.031..0.032 rows=1 loops=1)
          Buffers: shared hit=4
          ->  Index Scan using task_owner_id_task_date_id_idx on task t  (cost=0.42..387.57 rows=500 width=48) (actual time=0.030..0.030 rows=1 loops=1)
                Index Cond: (owner_id = 1)
                Buffers: shared hit=4
  InitPlan 2 (returns $1)
    ->  Limit  (cost=0.42..1.19 rows=1 width=48) (actual time=0.008..0.009 rows=1 loops=1)
          Buffers: shared hit=4
          ->  Index Scan using task_owner_id_task_date_id_idx on task t_1  (cost=0.42..387.57 rows=500 width=48) (actual time=0.008..0.008 rows=1 loops=1)
                Index Cond: (owner_id = 1)
                Buffers: shared hit=4
  InitPlan 3 (returns $2)
    ->  Limit  (cost=0.42..1.19 rows=1 width=48) (actual time=0.008..0.008 rows=1 loops=1)
          Buffers: shared hit=4
          ->  Index Scan using task_owner_id_task_date_id_idx on task t_2  (cost=0.42..387.57 rows=500 width=48) (actual time=0.008..0.008 rows=1 loops=1)
                Index Cond: (owner_id = 1)
                Buffers: shared hit=4"
  InitPlan 4 (returns $3)
    ->  Limit  (cost=0.42..1.19 rows=1 width=48) (actual time=0.009..0.009 rows=1 loops=1)
          Buffers: shared hit=4
          ->  Index Scan using task_owner_id_task_date_id_idx on task t_3  (cost=0.42..387.57 rows=500 width=48) (actual time=0.009..0.009 rows=1 loops=1)
                Index Cond: (owner_id = 1)
                Buffers: shared hit=4

рддреЛрдЪ рд░реЗрдХреЙрд░реНрдб рек рд╡реЗрд│рд╛ "рд╢реЛрдзрд▓рд╛" рдЧреЗрд▓рд╛... PostgreSQL резрез рдкрд░реНрдпрдВрдд, рд╣реЗ рд╡рд░реНрддрди рдирд┐рдпрдорд┐рддрдкрдгреЗ рдЖрдврд│рдд рд╣реЛрддреЗ рдЖрдгрд┐ рддреНрдпрд╛рд╡рд░ рдЙрдкрд╛рдп рдореНрд╣рдгрдЬреЗ рддреЗ CTE рдордзреНрдпреЗ "рд░реЕрдк" рдХрд░рдгреЗ, рдЬреЗ рдпрд╛ рдЖрд╡реГрддреНрддреНрдпрд╛рдВрдордзреНрдпреЗ рдСрдкреНрдЯрд┐рдорд╛рдпрдЭрд░рд╕рд╛рдареА рдПрдХ рдкрд░рд┐рдкреВрд░реНрдг рдорд░реНрдпрд╛рджрд╛ рдЖрд╣реЗ.

рд░рд┐рдХрд░реНрд╕рд┐рд╡реНрд╣ рдЕтАНреЕрдХреНрдпреБрдореНрдпреБрд▓реЗрдЯрд░

рдорд╛рдЧреАрд▓ рдЖрд╡реГрддреНрддреАрдд, рдЖрдкрдг рдПрдХреВрдг рд╡рд╛рдЪрд▓реЗ репремреж рдУрд│реА рдЖрд╡рд╢реНрдпрдХ рдЕрд╕рд▓реЗрд▓реНрдпрд╛ реиреж рд╕рд╛рдареА. рдЖрддрд╛ репремреж рдирд╛рд╣реА, рддрд░ рддреНрдпрд╛рд╣реВрдирд╣реА рдХрдореА - рд╣реЗ рд╢рдХреНрдп рдЖрд╣реЗ рдХрд╛?

рдЖрдкрд▓реНрдпрд╛рд▓рд╛ рдЖрд╡рд╢реНрдпрдХ рдЕрд╕рд▓реЗрд▓реЗ рдЬреНрдЮрд╛рди рд╡рд╛рдкрд░рдгреНрдпрд╛рдЪрд╛ рдкреНрд░рдпрддреНрди рдХрд░реВрдпрд╛ рдПрдХреВрдг 20 рд░реЗрдХреЙрд░реНрдб. рдореНрд╣рдгрдЬреЗрдЪ, рдЖрдкрдг рдЖрд╡рд╢реНрдпрдХ рд╕рдВрдЦреНрдпреЗрдкрд░реНрдпрдВрдд рдкреЛрд╣реЛрдЪреЗрдкрд░реНрдпрдВрддрдЪ рдбреЗрдЯрд╛ рд░реАрдбрд┐рдВрдЧрдЪреА рдкреБрдирд░рд╛рд╡реГрддреНрддреА рдХрд░реВ.

рдкрд╛рдпрд░реА рез: рд╕реБрд░реБрд╡рд╛рддреАрдЪреА рдпрд╛рджреА

рдЕрд░реНрдерд╛рдд, рдЖрдордЪреА реиреж рд░реЗрдХреЙрд░реНрдбрдЪреА "рд▓рдХреНрд╖реНрдп" рдпрд╛рджреА рдЖрдордЪреНрдпрд╛ рдорд╛рд▓рдХ_рдЖрдпрдбреА рдХреА рдкреИрдХреА рдПрдХрд╛рдЪреНрдпрд╛ "рдкрд╣рд┐рд▓реНрдпрд╛" рд░реЗрдХреЙрд░реНрдбрдиреЗ рд╕реБрд░реВ рдЭрд╛рд▓реА рдкрд╛рд╣рд┐рдЬреЗ. рддрд░, рдкреНрд░рдердо рддреНрдпрд╛ рд╢реЛрдзреВрдпрд╛ рдкреНрд░рддреНрдпреЗрдХ рдХрд┐рд▓реНрд▓реАрд╕рд╛рдареА "рдкрд╣рд┐рд▓реЗ" рдЖрдгрд┐ рддреЗ рдпрд╛рджреАрдд рдЬреЛрдбрд╛, рдЖрдкрд▓реНрдпрд╛рд▓рд╛ рд╣рд╡реНрдпрд╛ рддреНрдпрд╛ рдХреНрд░рдорд╛рдиреЗ рдХреНрд░рдорд╡рд╛рд░реА рд▓рд╛рд╡рд╛ - (рдХрд╛рд░реНрдп_рддрд╛рд░реАрдЦ, рдЖрдпрдбреА).

SQL HowTo: рдХреНрд╡реЗрд░реАрдордзреНрдпреЗ рдереЗрдЯ рдПрдХ while-loop рд▓рд┐рд╣рд╛, рдХрд┐рдВрд╡рд╛ "Elementary three-way"

рдкрд╛рдпрд░реА реи: "рдкреБрдвреАрд▓" рдиреЛрдВрджреА рд╢реЛрдзрд╛

рдЖрддрд╛ рдЬрд░ рдЖрдкрдг рдЖрдкрд▓реНрдпрд╛ рдпрд╛рджреАрддреАрд▓ рдкрд╣рд┐рд▓реА рдиреЛрдВрдж рдШреЗрддрд▓реА рдЖрдгрд┐ рд╕реБрд░реБрд╡рд╛рдд рдХреЗрд▓реА рддрд░ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХрд╛рдд рдЖрдгрдЦреА "рдкрд╛рдп" рдЯрд╛рдХрд╛ рдорд╛рд▓рдХ_рдЖрдпрдбреА рдХреА рдЬрддрди рдХрд░реВрди, рд╕рд╛рдкрдбрд▓реЗрд▓реЗ рд╕рд░реНрд╡ рд░реЗрдХреЙрд░реНрдб рдкрд░рд┐рдгрд╛рдореА рдирд┐рд╡рдбреАрддреАрд▓ рдЕрдЧрджреА рдкреБрдвреАрд▓ рд░реЗрдХреЙрд░реНрдб рдЕрд╕рддреАрд▓. рдЕрд░реНрдерд╛рдд, рдлрдХреНрдд рдЬреЛрдкрд░реНрдпрдВрдд рдЖрдкрдг рд▓рд╛рдЧреВ рдХреЗрд▓реЗрд▓реА рдХреА рдУрд▓рд╛рдВрдбрдд рдирд╛рд╣реА рддреЛрдкрд░реНрдпрдВрдд рдпрд╛рджреАрддреАрд▓ рджреБрд╕рд░реА рдиреЛрдВрдж.

рдЬрд░ рдЕрд╕реЗ рджрд┐рд╕реВрди рдЖрд▓реЗ рдХреА рдЖрдкрдг рджреБрд╕рд░реА рдиреЛрдВрдж "рдХреНрд░реЙрд╕" рдХреЗрд▓реА, рддрд░ рдкрд╣рд┐рд▓реНрдпрд╛рдРрд╡рдЬреА рд╢реЗрд╡рдЯрдЪреА рд╡рд╛рдЪрд▓реЗрд▓реА рдиреЛрдВрдж рдпрд╛рджреАрдд рдЬреЛрдбрд╛рд╡реА. (рддреНрдпрд╛рдЪ рдорд╛рд▓рдХрд╛рдЪреНрдпрд╛_рдЖрдпрдбреАрд╕рд╣), рддреНрдпрд╛рдирдВрддрд░ рдЖрдореНрд╣реА рдпрд╛рджреА рдкреБрдиреНрд╣рд╛ рдХреНрд░рдорд╡рд╛рд░реА рд▓рд╛рд╡рддреЛ.

SQL HowTo: рдХреНрд╡реЗрд░реАрдордзреНрдпреЗ рдереЗрдЯ рдПрдХ while-loop рд▓рд┐рд╣рд╛, рдХрд┐рдВрд╡рд╛ "Elementary three-way"

рдореНрд╣рдгрдЬреЗрдЪ, рдЖрдкрд▓реНрдпрд╛рд▓рд╛ рдиреЗрд╣рдореАрдЪ рдЕрд╕реЗ рдЖрдврд│рддреЗ рдХреА рдпрд╛рджреАрдордзреНрдпреЗ рдкреНрд░рддреНрдпреЗрдХ рдХреАрд╕рд╛рдареА рдПрдХрд╛рдкреЗрдХреНрд╖рд╛ рдЬрд╛рд╕реНрдд рдиреЛрдВрджреА рдирд╛рд╣реАрдд (рдЬрд░ рдиреЛрдВрджреА рд╕рдВрдкрд▓реНрдпрд╛ рдЖрдгрд┐ рдЖрдкрдг рддреНрдпрд╛ "рдХреНрд░реЙрд╕" рдХреЗрд▓реНрдпрд╛ рдирд╛рд╣реАрдд, рддрд░ рдкрд╣рд┐рд▓реА рдиреЛрдВрдж рдпрд╛рджреАрддреВрди рдЧрд╛рдпрдм рд╣реЛрдИрд▓ рдЖрдгрд┐ рдХрд╛рд╣реАрд╣реА рдЬреЛрдбрд▓реЗ рдЬрд╛рдгрд╛рд░ рдирд╛рд╣реА), рдЖрдгрд┐ рддреЗ рдиреЗрд╣рдореА рдХреНрд░рдорд╡рд╛рд░реА рд▓рд╛рд╡рд▓реЗрд▓реЗ рдЕреЕрдкреНрд▓рд┐рдХреЗрд╢рди рдХреА (рдЯрд╛рд╕реНрдХ_рдбреЗрдЯ, рдЖрдпрдбреА) рдЪреНрдпрд╛ рдЪрдврддреНрдпрд╛ рдХреНрд░рдорд╛рдиреЗ.

SQL HowTo: рдХреНрд╡реЗрд░реАрдордзреНрдпреЗ рдереЗрдЯ рдПрдХ while-loop рд▓рд┐рд╣рд╛, рдХрд┐рдВрд╡рд╛ "Elementary three-way"

рдкрд╛рдпрд░реА рей: рд░реЗрдХреЙрд░реНрдб рдлрд┐рд▓реНрдЯрд░ рдХрд░рд╛ рдЖрдгрд┐ рд╡рд┐рд╕реНрддреГрдд рдХрд░рд╛

рдЖрдордЪреНрдпрд╛ рд░рд┐рдХрд░реНрд╕рд┐рд╡реНрд╣ рдирд┐рд╡рдбреАрдЪреНрдпрд╛ рдХрд╛рд╣реА рдУрд│реАрдВрдордзреНрдпреЗ, рдХрд╛рд╣реА рдиреЛрдВрджреА rv рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдиреЛрдВрджреА - рдЖрдкрд▓реНрдпрд╛рд▓рд╛ рдкреНрд░рдердо "рдпрд╛рджреАрддреАрд▓ рджреБрд╕рд▒реНрдпрд╛ рдиреЛрдВрджреАрдЪреА рд╕реАрдорд╛ рдУрд▓рд╛рдВрдбрдгреЗ" рд╕рд╛рд░рдЦреНрдпрд╛ рдиреЛрдВрджреА рдЖрдврд│рддрд╛рдд рдЖрдгрд┐ рдирдВрддрд░ рддреНрдпрд╛ рдпрд╛рджреАрддреАрд▓ рдкрд╣рд┐рд▓реНрдпрд╛ рдиреЛрдВрджреА рдореНрд╣рдгреВрди рдмрджрд▓рддрд╛рдд. рдореНрд╣рдгреВрди, рдкрд╣рд┐рд▓реА рдШрдЯрдирд╛ рдлрд┐рд▓реНрдЯрд░ рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ.

рднрдпрд╛рдирдХ рд╢реЗрд╡рдЯрдЪрд╛ рдкреНрд░рд╢реНрди

WITH RECURSIVE T AS (
  -- #1 : ╨╖╨░╨╜╨╛╤Б╨╕╨╝ ╨▓ ╤Б╨┐╨╕╤Б╨╛╨║ "╨┐╨╡╤А╨▓╤Л╨╡" ╨╖╨░╨┐╨╕╤Б╨╕ ╨┐╨╛ ╨║╨░╨╢╨┤╨╛╨╝╤Г ╨╕╨╖ ╨║╨╗╤О╤З╨╡╨╣ ╨╜╨░╨▒╨╛╤А╨░
  WITH wrap AS ( -- "╨╝╨░╤В╨╡╤А╨╕╨░╨╗╨╕╨╖╤Г╨╡╨╝" record'╤Л, ╤З╤В╨╛╨▒╤Л ╨╛╨▒╤А╨░╤Й╨╡╨╜╨╕╨╡ ╨║ ╨┐╨╛╨╗╤П╨╝ ╨╜╨╡ ╨▓╤Л╨╖╤Л╨▓╨░╨╗╨╛ ╤Г╨╝╨╜╨╛╨╢╨╡╨╜╨╕╤П InitPlan/SubPlan
    WITH T AS (
      SELECT
        (
          SELECT
            r
          FROM
            task r
          WHERE
            owner_id = unnest
          ORDER BY
            task_date, id
          LIMIT 1
        ) r
      FROM
        unnest('{1,2,4,8,16,32,64,128,256,512}'::integer[])
    )
    SELECT
      array_agg(r ORDER BY (r).task_date, (r).id) list -- ╤Б╨╛╤А╤В╨╕╤А╤Г╨╡╨╝ ╤Б╨┐╨╕╤Б╨╛╨║ ╨▓ ╨╜╤Г╨╢╨╜╨╛╨╝ ╨┐╨╛╤А╤П╨┤╨║╨╡
    FROM
      T
  )
  SELECT
    list
  , list[1] rv
  , FALSE not_cross
  , 0 size
  FROM
    wrap
UNION ALL
  -- #2 : ╨▓╤Л╤З╨╕╤В╤Л╨▓╨░╨╡╨╝ ╨╖╨░╨┐╨╕╤Б╨╕ 1-╨│╨╛ ╨┐╨╛ ╨┐╨╛╤А╤П╨┤╨║╤Г ╨║╨╗╤О╤З╨░, ╨┐╨╛╨║╨░ ╨╜╨╡ ╨┐╨╡╤А╨╡╤И╨░╨│╨╜╨╡╨╝ ╤З╨╡╤А╨╡╨╖ ╨╖╨░╨┐╨╕╤Б╤М 2-╨│╨╛
  SELECT
    CASE
      -- ╨╡╤Б╨╗╨╕ ╨╜╨╕╤З╨╡╨│╨╛ ╨╜╨╡ ╨╜╨░╨╣╨┤╨╡╨╜╨╛ ╨┤╨╗╤П ╨║╨╗╤О╤З╨░ 1-╨╣ ╨╖╨░╨┐╨╕╤Б╨╕
      WHEN X._r IS NOT DISTINCT FROM NULL THEN
        T.list[2:] -- ╤Г╨▒╨╕╤А╨░╨╡╨╝ ╨╡╨╡ ╨╕╨╖ ╤Б╨┐╨╕╤Б╨║╨░
      -- ╨╡╤Б╨╗╨╕ ╨╝╤Л ╨Э╨Х ╨┐╨╡╤А╨╡╤Б╨╡╨║╨╗╨╕ ╨┐╤А╨╕╨║╨╗╨░╨┤╨╜╨╛╨╣ ╨║╨╗╤О╤З 2-╨╣ ╨╖╨░╨┐╨╕╤Б╨╕
      WHEN X.not_cross THEN
        T.list -- ╨┐╤А╨╛╤Б╤В╨╛ ╨┐╤А╨╛╤В╤П╨│╨╕╨▓╨░╨╡╨╝ ╤В╨╛╤В ╨╢╨╡ ╤Б╨┐╨╕╤Б╨╛╨║ ╨▒╨╡╨╖ ╨╝╨╛╨┤╨╕╤Д╨╕╨║╨░╤Ж╨╕╨╣
      -- ╨╡╤Б╨╗╨╕ ╨▓ ╤Б╨┐╨╕╤Б╨║╨╡ ╤Г╨╢╨╡ ╨╜╨╡╤В 2-╨╣ ╨╖╨░╨┐╨╕╤Б╨╕
      WHEN T.list[2] IS NULL THEN
        -- ╨┐╤А╨╛╤Б╤В╨╛ ╨▓╨╛╨╖╨▓╤А╨░╤Й╨░╨╡╨╝ ╨┐╤Г╤Б╤В╨╛╨╣ ╤Б╨┐╨╕╤Б╨╛╨║
        '{}'
      -- ╨┐╨╡╤А╨╡╤Б╨╛╤А╤В╨╕╤А╨╛╨▓╤Л╨▓╨░╨╡╨╝ ╤Б╨╗╨╛╨▓╨░╤А╤М, ╤Г╨▒╨╕╤А╨░╤П 1-╤О ╨╖╨░╨┐╨╕╤Б╤М ╨╕ ╨┤╨╛╨▒╨░╨▓╨╗╤П╤П ╨┐╨╛╤Б╨╗╨╡╨┤╨╜╤О╤О ╨╕╨╖ ╨╜╨░╨╣╨┤╨╡╨╜╨╜╤Л╤Е
      ELSE (
        SELECT
          coalesce(T.list[2] || array_agg(r ORDER BY (r).task_date, (r).id), '{}')
        FROM
          unnest(T.list[3:] || X._r) r
      )
    END
  , X._r
  , X.not_cross
  , T.size + X.not_cross::integer
  FROM
    T
  , LATERAL(
      WITH wrap AS ( -- "╨╝╨░╤В╨╡╤А╨╕╨░╨╗╨╕╨╖╤Г╨╡╨╝" record
        SELECT
          CASE
            -- ╨╡╤Б╨╗╨╕ ╨▓╤Б╨╡-╤В╨░╨║╨╕ "╨┐╨╡╤А╨╡╤И╨░╨│╨╜╤Г╨╗╨╕" ╤З╨╡╤А╨╡╨╖ 2-╤О ╨╖╨░╨┐╨╕╤Б╤М
            WHEN NOT T.not_cross
              -- ╤В╨╛ ╨╜╤Г╨╢╨╜╨░╤П ╨╖╨░╨┐╨╕╤Б╤М - ╨┐╨╡╤А╨▓╨░╤П ╨╕╨╖ ╤Б╨┐╨┐╨╕╤Б╨║╨░
              THEN T.list[1]
            ELSE ( -- ╨╡╤Б╨╗╨╕ ╨╜╨╡ ╨┐╨╡╤А╨╡╤Б╨╡╨║╨╗╨╕, ╤В╨╛ ╨║╨╗╤О╤З ╨╛╤Б╤В╨░╨╗╤Б╤П ╨║╨░╨║ ╨▓ ╨┐╤А╨╡╨┤╤Л╨┤╤Г╤Й╨╡╨╣ ╨╖╨░╨┐╨╕╤Б╨╕ - ╨╛╤В╤В╨░╨╗╨║╨╕╨▓╨░╨╡╨╝╤Б╤П ╨╛╤В ╨╜╨╡╨╡
              SELECT
                _r
              FROM
                task _r
              WHERE
                owner_id = (rv).owner_id AND
                (task_date, id) > ((rv).task_date, (rv).id)
              ORDER BY
                task_date, id
              LIMIT 1
            )
          END _r
      )
      SELECT
        _r
      , CASE
          -- ╨╡╤Б╨╗╨╕ 2-╨╣ ╨╖╨░╨┐╨╕╤Б╨╕ ╤Г╨╢╨╡ ╨╜╨╡╤В ╨▓ ╤Б╨┐╨╕╤Б╨║╨╡, ╨╜╨╛ ╨╝╤Л ╤Е╨╛╤В╤М ╤З╤В╨╛-╤В╨╛ ╨╜╨░╤И╨╗╨╕
          WHEN list[2] IS NULL AND _r IS DISTINCT FROM NULL THEN
            TRUE
          ELSE -- ╨╜╨╕╤З╨╡╨│╨╛ ╨╜╨╡ ╨╜╨░╤И╨╗╨╕ ╨╕╨╗╨╕ "╨┐╨╡╤А╨╡╤И╨░╨│╨╜╤Г╨╗╨╕"
            coalesce(((_r).task_date, (_r).id) < ((list[2]).task_date, (list[2]).id), FALSE)
        END not_cross
      FROM
        wrap
    ) X
  WHERE
    T.size < 20 AND -- ╨╛╨│╤А╨░╨╜╨╕╤З╨╕╨▓╨░╨╡╨╝ ╤В╤Г╤В ╨║╨╛╨╗╨╕╤З╨╡╤Б╤В╨▓╨╛
    T.list IS DISTINCT FROM '{}' -- ╨╕╨╗╨╕ ╨┐╨╛╨║╨░ ╤Б╨┐╨╕╤Б╨╛╨║ ╨╜╨╡ ╨║╨╛╨╜╤З╨╕╨╗╤Б╤П
)
-- #3 : "╤А╨░╨╖╨▓╨╛╤А╨░╤З╨╕╨▓╨░╨╡╨╝" ╨╖╨░╨┐╨╕╤Б╨╕ - ╨┐╨╛╤А╤П╨┤╨╛╨║ ╨│╨░╤А╨░╨╜╤В╨╕╤А╨╛╨▓╨░╨╜ ╨┐╨╛ ╨┐╨╛╤Б╤В╤А╨╛╨╡╨╜╨╕╤О
SELECT
  (rv).*
FROM
  T
WHERE
  not_cross; -- ╨▒╨╡╤А╨╡╨╝ ╤В╨╛╨╗╤М╨║╨╛ "╨╜╨╡╨┐╨╡╤А╨╡╤Б╨╡╨║╨░╤О╤Й╨╕╨╡" ╨╖╨░╨┐╨╕╤Б╨╕

SQL HowTo: рдХреНрд╡реЗрд░реАрдордзреНрдпреЗ рдереЗрдЯ рдПрдХ while-loop рд▓рд┐рд╣рд╛, рдХрд┐рдВрд╡рд╛ "Elementary three-way"
[explain.tensor.ru рдкрд╣рд╛]

рддрд░ рдЖрдкрдг рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреА рд╡реЗрд│реЗрдЪреНрдпрд╛ реиреж% рд╕рд╛рдареА релреж% рдбреЗрдЯрд╛ рд░реАрдбрдЪрд╛ рд╡реНрдпрд╛рдкрд╛рд░ рдХреЗрд▓рд╛рдореНрд╣рдгрдЬреЗрдЪ, рдЬрд░ рддреБрдореНрд╣рд╛рд▓рд╛ рдЕрд╕реЗ рдорд╛рдирдгреНрдпрд╛рдЪреЗ рдХрд╛рд░рдг рдЕрд╕реЗрд▓ рдХреА рд╡рд╛рдЪрди рдордВрдж рдЕрд╕реВ рд╢рдХрддреЗ (рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, рдбреЗрдЯрд╛ рдмрд╣реБрддреЗрдХрджрд╛ рдХреЕрд╢реЗрдордзреНрдпреЗ рдирд╕рддреЛ рдЖрдгрд┐ рдбрд┐рд╕реНрдХрд╡рд░реВрди рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд░рд╛рд╡рд╛ рд▓рд╛рдЧрддреЛ), рддрд░ рд╣реА рдкрджреНрдзрдд рд╡рд╛рдЪрдирд╛рд╡рд░реАрд▓ рддреБрдордЪрд╛ рдЕрд╡рд▓рдВрдмрд┐рддреНрд╡ рдХрдореА рдХрд░реВ рд╢рдХрддреЗ.

рдХрд╛рд╣реАрд╣реА рдЕрд╕реЛ, "рднреЛрд│реНрдпрд╛" рдкрд╣рд┐рд▓реНрдпрд╛ рдкрд░реНрдпрд╛рдпрд╛рдкреЗрдХреНрд╖рд╛ рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреАрдЪрд╛ рд╡реЗрд│ рдЪрд╛рдВрдЧрд▓рд╛ рд╣реЛрддрд╛. рдкрдг рдпрд╛ рддреАрди рдкрд░реНрдпрд╛рдпрд╛рдВрдкреИрдХреА рдХреЛрдгрддрд╛ рдкрд░реНрдпрд╛рдп рд╡рд╛рдкрд░рд╛рдпрдЪрд╛ рд╣реЗ рддреБрдордЪреНрдпрд╛рд╡рд░ рдЕрд╡рд▓рдВрдмреВрди рдЖрд╣реЗ.

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

DDoS рд╕рдВрд░рдХреНрд╖рдг, VPS VDS рд╕рд░реНрд╡реНрд╣рд░ рдЕрд╕рд▓реЗрд▓реНрдпрд╛ рд╕рд╛рдЗрдЯрд╕рд╛рдареА рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рд╣реЛрд╕реНрдЯрд┐рдВрдЧ рдЦрд░реЗрджреА рдХрд░рд╛ ЁЯФе рдбреАрдбреЙрд╕ рд╕рдВрд░рдХреНрд╖рдгрд╛рд╕рд╣ рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рд╡реЗрдмрд╕рд╛рдЗрдЯ рд╣реЛрд╕реНрдЯрд┐рдВрдЧ, рд╡реНрд╣реАрдкреАрдПрд╕ (VPS) рд╡реНрд╣реАрдбреАрдПрд╕ (VDS) рд╕рд░реНрд╡реНрд╣рд░реНрд╕ рдЦрд░реЗрджреА рдХрд░рд╛ | ProHoster