PK рдмрд┐рдирд╛ рддрд╛рд▓рд┐рдХрд╛рдмрд╛рдЯ рдХреНрд▓реЛрди рд░реЗрдХрд░реНрдбрд╣рд░реВ рдЦрд╛рд▓реА рдЧрд░реНрджреИ

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

PK рдмрд┐рдирд╛ рддрд╛рд▓рд┐рдХрд╛рдмрд╛рдЯ рдХреНрд▓реЛрди рд░реЗрдХрд░реНрдбрд╣рд░реВ рдЦрд╛рд▓реА рдЧрд░реНрджреИ

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

рдЕрдирд╛рд╡рд╢реНрдпрдХ рдХреНрд▓реЛрдирд╣рд░реВрдХреЛ рдбрд╛рдЯрд╛рдмреЗрд╕ рдХрд╕рд░реА рд╣рдЯрд╛рдЙрдиреЗ?

рдЬрдм PK рд╕рд╣рдпреЛрдЧреА рд╣реЛрдЗрди

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

рдЙрджрд╛рд╣рд░рдг рдХреЛ рд▓рд╛рдЧреА, рдпрджрд┐ рд╕реНрд░реЛрдд рдкреНрд░рдгрд╛рд▓реА рдХреЛ рд╢реБрджреНрдзрддрд╛ рдбрд╛рдЯрд╛рдмреЗрд╕ рдорд╛ рдХреНрд╖реЗрддреНрд░ рдХреЛ рд╢реБрджреНрдзрддрд╛ рднрдиреНрджрд╛ рдЙрдЪреНрдЪ рдЫ:

metric   | ts                  | data
--------------------------------------------------
cpu.busy | 2019-12-20 00:00:00 | {"value" : 12.34}
cpu.busy | 2019-12-20 00:00:01 | {"value" : 10}
cpu.busy | 2019-12-20 00:00:01 | {"value" : 11.2}
cpu.busy | 2019-12-20 00:00:03 | {"value" : 15.7}

рддрдкрд╛рдИрдВрд▓реЗ рдпрд╛рдж рдЧрд░реНрдиреБрднрдпреЛ? 00:00:02 рдХреЛ рд╕рдЯреНрдЯрд╛ рдХрд╛рдЙрдиреНрдЯрдбрд╛рдЙрди рдПрдХ рд╕реЗрдХреЗрдиреНрдб рдкрд╣рд┐рд▓реЗ ts рдХреЛ рд╕рд╛рде рдбрд╛рдЯрд╛рдмреЗрд╕рдорд╛ рд░реЗрдХрд░реНрдб рдЧрд░рд┐рдПрдХреЛ рдерд┐рдпреЛ, рддрд░ рдЕрдиреБрдкреНрд░рдпреЛрдЧрдХреЛ рджреГрд╖реНрдЯрд┐рдХреЛрдгрдмрд╛рдЯ рдПрдХрджрдо рдорд╛рдиреНрдп рд░рд╣реНрдпреЛ (рд╕рдмреИ рдкрдЫрд┐, рдбрд╛рдЯрд╛ рдорд╛рдирд╣рд░реВ рдлрд░рдХ рдЫрдиреН!)ред

рдЕрд╡рд╢реНрдп рдкрдирд┐ рддрдкрд╛рдИрдВ рдпреЛ рдЧрд░реНрди рд╕рдХреНрдиреБрд╣реБрдиреНрдЫ PK(рдореЗрдЯреНрд░рд┐рдХ, ts) - рддрд░ рддреНрдпрд╕реЛрднрдП рд╣рд╛рдореА рд╡реИрдз рдбрд╛рдЯрд╛рдХреЛ рд▓рд╛рдЧрд┐ рд╕рдореНрдорд┐рд▓рди рд╡рд┐рд╡рд╛рджрд╣рд░реВ рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрдиреЗрдЫреМрдВред

рдЧрд░реНрди рд╕рдХреНрдЫреБ PK(рдореЗрдЯреНрд░рд┐рдХ, ts, рдбреЗрдЯрд╛) - рддрд░ рдпрд╕рд▓реЗ рдпрд╕рдХреЛ рдорд╛рддреНрд░рд╛ рдзреЗрд░реИ рдмрдврд╛рдЙрдБрдЫ, рдЬреБрди рд╣рд╛рдореА рдкреНрд░рдпреЛрдЧ рдЧрд░реНрджреИрдиреМрдВред

рддреНрдпрд╕рдХрд╛рд░рдг, рд╕рдмреИрднрдиреНрджрд╛ рд╕рд╣реА рд╡рд┐рдХрд▓реНрдк рдирд┐рдпрдорд┐рдд рдЧреИрд░-рдЕрджреНрд╡рд┐рддреАрдп рд╕реВрдЪрдХрд╛рдВрдХ рдмрдирд╛рдЙрдиреБ рд╣реЛ (рдореЗрдЯреНрд░рд┐рдХ, рдЯреАрдПрд╕) рд░ рдпрджрд┐ рддрд┐рдиреАрд╣рд░реВ рдЙрддреНрдкрдиреНрди рд╣реБрдиреНрдЫрдиреН рднрдиреЗ рддрдереНрдп рдкрдЫрд┐ рд╕рдорд╕реНрдпрд╛рд╣рд░реВ рд╕рдорд╛рдзрд╛рди рдЧрд░реНрдиреБрд╣реЛрд╕реНред

"рдХреНрд▓реЛрдирд┐рдХ рдпреБрджреНрдз рд╕реБрд░реБ рднрдПрдХреЛ рдЫ"

рдХреЗрд╣рд┐ рдкреНрд░рдХрд╛рд░рдХреЛ рджреБрд░реНрдШрдЯрдирд╛ рднрдпреЛ, рд░ рдЕрдм рд╣рд╛рдореАрд▓реЗ рдЯреЗрдмрд▓рдмрд╛рдЯ рдХреНрд▓реЛрди рд░реЗрдХрд░реНрдбрд╣рд░реВ рдирд╖реНрдЯ рдЧрд░реНрдиреБ рдкрд░реНрдЫред

PK рдмрд┐рдирд╛ рддрд╛рд▓рд┐рдХрд╛рдмрд╛рдЯ рдХреНрд▓реЛрди рд░реЗрдХрд░реНрдбрд╣рд░реВ рдЦрд╛рд▓реА рдЧрд░реНрджреИ

рдореВрд▓ рдбрд╛рдЯрд╛ рдореЛрдбреЗрд▓ рдЧрд░реМрдВ:

CREATE TABLE tbl(k text, v integer);

INSERT INTO tbl
VALUES
  ('a', 1)
, ('a', 3)
, ('b', 2)
, ('b', 2) -- oops!
, ('c', 3)
, ('c', 3) -- oops!!
, ('c', 3) -- oops!!
, ('d', 4)
, ('e', 5)
;

рдпрд╣рд╛рдБ рд╣рд╛рдореНрд░реЛ рд╣рд╛рдд рддреАрди рдкрдЯрдХ рдХрд╛рдореНрдкреНрдпреЛ, Ctrl+V рдЕрдбреНрдХрд┐рдпреЛ, рд░ рдЕрдм ...

рдкрд╣рд┐рд▓реЗ, рд╣рд╛рдореА рдмреБрдЭреМрдВ рдХрд┐ рд╣рд╛рдореНрд░реЛ рддрд╛рд▓рд┐рдХрд╛ рдзреЗрд░реИ рдареВрд▓реЛ рд╣реБрди рд╕рдХреНрдЫ, рддреНрдпрд╕реИрд▓реЗ рд╣рд╛рдореАрд▓реЗ рд╕рдмреИ рдХреНрд▓реЛрдирд╣рд░реВ рдлреЗрд▓рд╛ рдкрд╛рд░реЗрдкрдЫрд┐, рд╣рд╛рдореАрд▓рд╛рдИ рдореЗрдЯрд╛рдЙрдирдХреЛ рд▓рд╛рдЧрд┐ рд╢рд╛рдмреНрджрд┐рдХ рд░реВрдкрдорд╛ "рд╣рд╛рдореНрд░реЛ рдФрдВрд▓рд╛ рдкреЛрдХ" рдЧрд░реНрди рд╕рд▓реНрд▓рд╛рд╣ рджрд┐рдЗрдиреНрдЫред рддрд┐рдиреАрд╣рд░реВрд▓рд╛рдИ рдкреБрди: рдЦреЛрдЬреА рдмрд┐рдирд╛ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЕрднрд┐рд▓реЗрдЦрд╣рд░реВ.

рд░ рддреНрдпрд╣рд╛рдБ рдпрд╕реНрддреЛ рддрд░рд┐рдХрд╛ рдЫ - рдпреЛ ctid рджреНрд╡рд╛рд░рд╛ рд╕рдореНрдмреЛрдзрди рдЧрд░реНрджреИ, рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд░реЗрдХрд░реНрдб рдХреЛ рднреМрддрд┐рдХ рдкрд╣рд┐рдЪрд╛рдирдХрд░реНрддрд╛ред

рддреНрдпреЛ рд╣реЛ, рд╕рдмреИрднрдиреНрджрд╛ рдкрд╣рд┐рд▓реЗ, рд╣рд╛рдореАрд▓реЗ рддрд╛рд▓рд┐рдХрд╛ рдкрдЩреНрдХреНрддрд┐рдХреЛ рдкреВрд░реНрдг рд╕рд╛рдордЧреНрд░реАрдХреЛ рд╕рдиреНрджрд░реНрднрдорд╛ рд░реЗрдХрд░реНрдбрд╣рд░реВрдХреЛ ctid рд╕рдЩреНрдХрд▓рди рдЧрд░реНрди рдЖрд╡рд╢реНрдпрдХ рдЫред рд╕рд░рд▓ рд╡рд┐рдХрд▓реНрдк рднрдиреЗрдХреЛ рд╕рдореНрдкреВрд░реНрдг рд▓рд╛рдЗрдирд▓рд╛рдИ рдкрд╛рдардорд╛ рдХрд╛рд╕реНрдЯ рдЧрд░реНрдиреБ рд╣реЛ:

SELECT
  T::text
, array_agg(ctid) ctids
FROM
  tbl T
GROUP BY
  1;

t     | ctids
---------------------------------
(e,5) | {"(0,9)"}
(d,4) | {"(0,8)"}
(c,3) | {"(0,5)","(0,6)","(0,7)"}
(b,2) | {"(0,3)","(0,4)"}
(a,3) | {"(0,2)"}
(a,1) | {"(0,1)"}

рдпреЛ рдХрд╛рд╕реНрдЯ рдЧрд░реНрди рд╕рдореНрднрд╡ рдЫреИрди?рд╕рд┐рджреНрдзрд╛рдиреНрдд рдорд╛, рдпреЛ рдзреЗрд░реИ рдЕрд╡рд╕реНрдерд╛рдорд╛ рд╕рдореНрднрд╡ рдЫред рддрдкрд╛рдИрдВрд▓реЗ рдпреЛ рддрд╛рд▓рд┐рдХрд╛рдорд╛ рдлрд┐рд▓реНрдбрд╣рд░реВ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрди рд╕реБрд░реБ рдирдЧрд░реЗрд╕рдореНрдо рд╕рдорд╛рдирддрд╛ рдЕрдкрд░реЗрдЯрд░ рдмрд┐рдирд╛ рдкреНрд░рдХрд╛рд░:

CREATE TABLE tbl(k text, v integer, x point);
SELECT
  array_agg(ctid) ctids
FROM
  tbl T
GROUP BY
  T;
-- ERROR:  could not identify an equality operator for type tbl

рд╣реЛ, рд╣рд╛рдореА рддреБрд░реБрдиреНрддреИ рджреЗрдЦреНрдЫреМрдВ рдХрд┐ рдпрджрд┐ рдПрд░реЗрдорд╛ рдПрдХ рднрдиреНрджрд╛ рдмрдвреА рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рд╣рд░реВ рдЫрдиреН рднрдиреЗ, рдпреА рд╕рдмреИ рдХреНрд▓реЛрдирд╣рд░реВ рд╣реБрдиреНред рддрд┐рдиреАрд╣рд░реВрд▓рд╛рдИ рдЫреЛрдбреМрдВ:

SELECT
  unnest(ctids[2:])
FROM
  (
    SELECT
      array_agg(ctid) ctids
    FROM
      tbl T
    GROUP BY
      T::text
  ) T;

unnest
------
(0,6)
(0,7)
(0,4)

рдЫреЛрдЯреЛ рд▓реЗрдЦреНрди рдорди рдкрд░рд╛рдЙрдиреЗрд╣рд░реВрдХрд╛ рд▓рд╛рдЧрд┐рддрдкрд╛рдИрд▓реЗ рдпрд╕рд▓рд╛рдИ рдпрд╕рд░реА рдкрдирд┐ рд▓реЗрдЦреНрди рд╕рдХреНрдиреБрд╣реБрдиреНрдЫ:

SELECT
  unnest((array_agg(ctid))[2:])
FROM
  tbl T
GROUP BY
  T::text;

рд╕рд┐рд░рд┐рдпрд▓рд╛рдЗрдЬреНрдб рд╕реНрдЯреНрд░рд┐рдЩрдХреЛ рдорд╛рди рдЖрдлреИрдВрдорд╛ рд╣рд╛рдореАрд▓рд╛рдИ рдЪрд╛рдЦрд▓рд╛рдЧреНрджреЛ рдирднрдПрдХреЛрд▓реЗ, рд╣рд╛рдореАрд▓реЗ рдпрд╕рд▓рд╛рдИ рд╕рдмрдХреНрд╡реЗрд░реАрдХреЛ рдлрд░реНрдХрд╛рдЗрдПрдХреЛ рд╕реНрддрдореНрднрд╣рд░реВрдмрд╛рдЯ рдмрд╛рд╣рд┐рд░ рдлрд╛рд▓рд┐рджреНрдпреМрдВред

рддреНрдпрд╣рд╛рдБ рдХреЗрд╣рд┐ рдЧрд░реНрди рдмрд╛рдБрдХреА рдЫ - рд╣рд╛рдореАрд▓реЗ рдкреНрд░рд╛рдкреНрдд рдЧрд░реЗрдХреЛ рд╕реЗрдЯ рдкреНрд░рдпреЛрдЧ рдЧрд░реА DELETE рдмрдирд╛рдЙрдиреБрд╣реЛрд╕реН:

DELETE FROM
  tbl
WHERE
  ctid = ANY(ARRAY(
    SELECT
      unnest(ctids[2:])
    FROM
      (
        SELECT
          array_agg(ctid) ctids
        FROM
          tbl T
        GROUP BY
          T::text
      ) T
  )::tid[]);

рдЖрдлреИрд▓рд╛рдИ рдЬрд╛рдБрдЪ рдЧрд░реМрдВ:

PK рдмрд┐рдирд╛ рддрд╛рд▓рд┐рдХрд╛рдмрд╛рдЯ рдХреНрд▓реЛрди рд░реЗрдХрд░реНрдбрд╣рд░реВ рдЦрд╛рд▓реА рдЧрд░реНрджреИ
[explan.tensor.ru рдорд╛ рд╣реЗрд░реНрдиреБрд╣реЛрд╕реН]

рд╣реЛ, рд╕рдмреИ рдХреБрд░рд╛ рд╕рд╣реА рдЫ: рд╣рд╛рдореНрд░реЛ 3 рд░реЗрдХрд░реНрдбрд╣рд░реВ рд╕рдореНрдкреВрд░реНрдг рддрд╛рд▓рд┐рдХрд╛рдХреЛ рдорд╛рддреНрд░ рд╕реЗрдХ рд╕реНрдХреНрдпрд╛рдирдХрд╛ рд▓рд╛рдЧрд┐ рдЪрдпрди рдЧрд░рд┐рдПрдХреЛ рдерд┐рдпреЛ, рд░ рдбреЗрдЯрд╛ рдЦреЛрдЬреНрдирдХреЛ рд▓рд╛рдЧрд┐ рдореЗрдЯрд╛рдЙрдиреЗ рдиреЛрдб рдкреНрд░рдпреЛрдЧ рдЧрд░рд┐рдПрдХреЛ рдерд┐рдпреЛред Tid рд╕реНрдХреНрдпрд╛рди рд╕рдВрдЧ рдПрдХрд▓ рдкрд╛рд╕:

->  Tid Scan on tbl (actual time=0.050..0.051 rows=3 loops=1)
      TID Cond: (ctid = ANY ($0))

рдпрджрд┐ рддрдкрд╛рдИрдВрд▓реЗ рдзреЗрд░реИ рд░реЗрдХрд░реНрдбрд╣рд░реВ рдЦрд╛рд▓реА рдЧрд░реНрдиреБрднрдпреЛ рднрдиреЗ, VACUUM ANALYZE рдЪрд▓рд╛рдЙрди рдирдмрд┐рд░реНрд╕рдиреБрд╣реЛрд╕реН.

рдареВрд▓реЛ рддрд╛рд▓рд┐рдХрд╛ рд░ рдбреБрдкреНрд▓рд┐рдХреЗрдЯрд╣рд░реВрдХреЛ рдареВрд▓реЛ рд╕рдВрдЦреНрдпрд╛рдХреЛ рд▓рд╛рдЧрд┐ рдЬрд╛рдБрдЪ рдЧрд░реМрдВ:

TRUNCATE TABLE tbl;

INSERT INTO tbl
SELECT
  chr(ascii('a'::text) + (random() * 26)::integer) k -- a..z
, (random() * 100)::integer v -- 0..99
FROM
  generate_series(1, 10000) i;

PK рдмрд┐рдирд╛ рддрд╛рд▓рд┐рдХрд╛рдмрд╛рдЯ рдХреНрд▓реЛрди рд░реЗрдХрд░реНрдбрд╣рд░реВ рдЦрд╛рд▓реА рдЧрд░реНрджреИ
[explan.tensor.ru рдорд╛ рд╣реЗрд░реНрдиреБрд╣реЛрд╕реН]

рддреНрдпрд╕реИрд▓реЗ, рд╡рд┐рдзрд┐ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рдХрд╛рдо рдЧрд░реНрджрдЫ, рддрд░ рдпреЛ рдХреЗрд╣рд┐ рд╕рд╛рд╡рдзрд╛рдиреА рд╕рдВрдЧ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдиреБрдкрд░реНрдЫред рдХрд┐рдирднрдиреЗ рдореЗрдЯрд╛рдЗрдПрдХрд╛ рдкреНрд░рддреНрдпреЗрдХ рд░реЗрдХрд░реНрдбрдХреЛ рд▓рд╛рдЧрд┐, рдЯрд┐рдб рд╕реНрдХреНрдпрд╛рдирдорд╛ рдкрдвреНрдиреЗ рдПрдЙрдЯрд╛ рдбрд╛рдЯрд╛ рдкреГрд╖реНрда рд╣реБрдиреНрдЫ, рд░ рдПрдЙрдЯрд╛ рдореЗрдЯрд╛рдЗрдиреНрдЫред

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

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