PK рд╢рд┐рд╡рд╛рдп рдЯреЗрдмрд▓рдордзреВрди рдХреНрд▓реЛрди рд░реЗрдХреЙрд░реНрдб рд╕рд╛рдл рдХрд░рдгреЗ

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

PK рд╢рд┐рд╡рд╛рдп рдЯреЗрдмрд▓рдордзреВрди рдХреНрд▓реЛрди рд░реЗрдХреЙрд░реНрдб рд╕рд╛рдл рдХрд░рдгреЗ

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

рдЕрдирд╛рд╡рд╢реНрдпрдХ рдХреНрд▓реЛрдирдЪреНрдпрд╛ рдбреЗрдЯрд╛рдмреЗрд╕рдкрд╛рд╕реВрди рдореБрдХреНрдд рдХрд╕реЗ рдХрд░рд╛рд╡реЗ?

рдЬреЗрд╡реНрд╣рд╛ рдкреАрдХреЗ рдорджрддрдиреАрд╕ рдирд╕рддреЛ

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

рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, рдЬрд░ рд╕реНрддреНрд░реЛрдд рдкреНрд░рдгрд╛рд▓реАрдЪреА рдЕрдЪреВрдХрддрд╛ рдбреЗрдЯрд╛рдмреЗрд╕рдордзреАрд▓ рдлреАрд▓реНрдбрдЪреНрдпрд╛ рдЕрдЪреВрдХрддреЗрдкреЗрдХреНрд╖рд╛ рдЬрд╛рд╕реНрдд рдЕрд╕реЗрд▓ рддрд░:

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 рд╢рд┐рд╡рд╛рдп рдЯреЗрдмрд▓рдордзреВрди рдХреНрд▓реЛрди рд░реЗрдХреЙрд░реНрдб рд╕рд╛рдл рдХрд░рдгреЗ
[explain.tensor.ru рдкрд╣рд╛]

рд╣реЛрдп, рд╕рд░реНрд╡ рдХрд╛рд╣реА рдмрд░реЛрдмрд░ рдЖрд╣реЗ: рдЖрдордЪреНрдпрд╛ 3 рд░реЗрдХреЙрд░реНрдб рд╕рдВрдкреВрд░реНрдг рдЯреЗрдмрд▓рдЪреНрдпрд╛ рдлрдХреНрдд Seq рд╕реНрдХреЕрдирд╕рд╛рдареА рдирд┐рд╡рдбрд▓реНрдпрд╛ рдЧреЗрд▓реНрдпрд╛ рдЖрдгрд┐ рдбреЗрдЯрд╛ рд╢реЛрдзрдгреНрдпрд╛рд╕рд╛рдареА рд╣рдЯрд╡рд╛ рдиреЛрдб рд╡рд╛рдкрд░рд▓рд╛ рдЧреЗрд▓рд╛. рдЯрд┐рдб рд╕реНрдХреЕрдирд╕рд╣ рдПрдХрд▓ рдкрд╛рд╕:

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

рдЬрд░ рддреБрдореНрд╣реА рдмрд░реЗрдЪ рд░реЗрдХреЙрд░реНрдб рд╕рд╛рдл рдХреЗрд▓реЗ рдЕрд╕рддреАрд▓, рд╡реНрд╣реЕрдХреНрдпреВрдо рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдЪрд╛рд▓рд╡рд╛рдпрд▓рд╛ рд╡рд┐рд╕рд░реВ рдирдХрд╛.

рдЪрд▓рд╛ рдореЛрдареНрдпрд╛ рдЯреЗрдмрд▓рд╕рд╛рдареА рдЖрдгрд┐ рдореЛрдареНрдпрд╛ рд╕рдВрдЦреНрдпреЗрдиреЗ рдбреБрдкреНрд▓рд┐рдХреЗрдЯрд╕рд╣ рддрдкрд╛рд╕реВрдпрд╛:

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 рд╢рд┐рд╡рд╛рдп рдЯреЗрдмрд▓рдордзреВрди рдХреНрд▓реЛрди рд░реЗрдХреЙрд░реНрдб рд╕рд╛рдл рдХрд░рдгреЗ
[explain.tensor.ru рдкрд╣рд╛]

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

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

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдЬреЛрдбрд╛