PK เชตเช—เชฐเชจเชพ เชŸเซ‡เชฌเชฒเชฎเชพเช‚เชฅเซ€ เช•เซเชฒเซ‹เชจ เชฐเซ‡เช•เซ‹เชฐเซเชกเซเชธ เชธเชพเชซ เช•เชฐเชตเซเช‚

เชเชตเซ€ เชชเชฐเชฟเชธเซเชฅเชฟเชคเชฟเช“ เชนเซ‹เชฏ เช›เซ‡ เชœเซเชฏเชพเชฐเซ‡ เชชเซเชฐเชพเชฅเชฎเชฟเช• เช•เซ€ เชตเช—เชฐเชจเชพ เช•เซ‹เชทเซเชŸเช•เชฎเชพเช‚ เช…เชฅเชตเชพ เช•เซ‹เชˆ เช…เชจเซเชฏ เช…เชจเชจเซเชฏ เชธเซ‚เชšเช•เชพเช‚เช•, เชญเซ‚เชฒเชจเซ‡ เช•เชพเชฐเชฃเซ‡, เชชเชนเซ‡เชฒเชพเชฅเซ€ เชœ เช…เชธเซเชคเชฟเชคเซเชตเชฎเชพเช‚ เชฐเชนเซ‡เชฒเชพ เชฐเซ‡เช•เซ‹เชฐเซเชกเซเชธเชจเชพ เชธเช‚เชชเซ‚เชฐเซเชฃ เช•เซเชฒเซ‹เชจเซเชธ เชงเชฐเชพเชตเซ‡ เช›เซ‡.

PK เชตเช—เชฐเชจเชพ เชŸเซ‡เชฌเชฒเชฎเชพเช‚เชฅเซ€ เช•เซเชฒเซ‹เชจ เชฐเซ‡เช•เซ‹เชฐเซเชกเซเชธ เชธเชพเชซ เช•เชฐเชตเซเช‚

เช‰เชฆเชพเชนเชฐเชฃ เชคเชฐเซ€เช•เซ‡, เช•เชพเชฒเช•เซเชฐเชฎเชฟเช• เชฎเซ‡เชŸเซเชฐเชฟเช•เชจเชพ เชฎเซ‚เชฒเซเชฏเซ‹ COPY เชธเซเชŸเซเชฐเซ€เชฎเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€เชจเซ‡ PostgreSQL เชชเชฐ เชฒเช–เชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡, เช…เชจเซ‡ เชชเช›เซ€ เช…เชšเชพเชจเช• เชจเชฟเชทเซเชซเชณเชคเชพ เช†เชตเซ‡ เช›เซ‡, เช…เชจเซ‡ เช•เซ‡เชŸเชฒเชพเช• เชธเช‚เชชเซ‚เชฐเซเชฃเชชเชฃเซ‡ เชธเชฎเชพเชจ เชกเซ‡เชŸเชพ เชซเชฐเซ€เชฅเซ€ เช†เชตเซ‡ เช›เซ‡.

เชกเซ‡เชŸเชพเชฌเซ‡เชเชฎเชพเช‚เชฅเซ€ เชฌเชฟเชจเชœเชฐเซ‚เชฐเซ€ เช•เซเชฒเซ‹เชจเซเชธ เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เชฆเซ‚เชฐ เช•เชฐเชตเชพ?

เชœเซเชฏเชพเชฐเซ‡ เชชเซ€เช•เซ‡ เชฎเชฆเชฆเชฐเซ‚เชช เชจ เชนเซ‹เชฏ

เชธเซŒเชฅเซ€ เชธเชฐเชณ เช‰เชชเชพเชฏ เช เช›เซ‡ เช•เซ‡ เช† เชชเชฐเชฟเชธเซเชฅเชฟเชคเชฟเชจเซ‡ เชถเชฐเซ‚เช†เชคเชฎเชพเช‚ เชœ เชฌเชจเชคเซ€ เช…เชŸเช•เชพเชตเชตเซ€. เช‰เชฆเชพเชนเชฐเชฃ เชคเชฐเซ€เช•เซ‡, PRIMARY KEY เชฒเชพเช—เซ เช•เชฐเซ€เชจเซ‡. เชชเชฐเช‚เชคเซ เชธเช‚เช—เซเชฐเชนเชฟเชค เชกเซ‡เชŸเชพเชจเซ€ เชฎเชพเชคเซเชฐเชพเชฎเชพเช‚ เชตเชงเชพเชฐเซ‹ เช•เชฐเซเชฏเชพ เชตเชฟเชจเชพ เช† เชนเช‚เชฎเซ‡เชถเชพ เชถเช•เซเชฏ เชจเชฅเซ€.

เช‰เชฆเชพเชนเชฐเชฃ เชคเชฐเซ€เช•เซ‡, เชœเซ‹ เชธเซเชฐเซ‹เชค เชธเชฟเชธเซเชŸเชฎเชจเซ€ เชšเซ‹เช•เชธเชพเชˆ เชกเซ‡เชŸเชพเชฌเซ‡เชเชฎเชพเช‚ เชซเซ€เชฒเซเชกเชจเซ€ เชšเซ‹เช•เชธเชพเชˆ เช•เชฐเชคเชพ เชตเชงเชพเชฐเซ‡ เชนเซ‹เชฏ:

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 เชเช•เชคเซเชฐเชฟเชค เช•เชฐเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡. เชธเซŒเชฅเซ€ เชธเชฐเชณ เชตเชฟเช•เชฒเซเชช เช เช›เซ‡ เช•เซ‡ เช†เช–เซ€ เชชเช‚เช•เซเชคเชฟเชจเซ‡ เชŸเซ‡เช•เซเชธเซเชŸเชฎเชพเช‚ เช•เชพเชธเซเชŸ เช•เชฐเซ‹:

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 เชฐเซ‡เช•เซ‹เชฐเซเชก เชธเชฎเช—เซเชฐ เช•เซ‹เชทเซเชŸเช•เชจเชพ เชเช• เชœ Seq เชธเซเช•เซ‡เชจเชฎเชพเช‚ เชชเชธเช‚เชฆ เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซเชฏเชพ เชนเชคเชพ, เช…เชจเซ‡ เชกเซ‡เชŸเชพ เชถเซ‹เชงเชตเชพ เชฎเชพเชŸเซ‡ Delete เชจเซ‹เชกเชจเซ‹ เช‰เชชเชฏเซ‹เช— เช•เชฐเชตเชพเชฎเชพเช‚ เช†เชตเซเชฏเซ‹ เชนเชคเซ‹. เชŸเชฟเชก เชธเซเช•เซ‡เชจ เชธเชพเชฅเซ‡ เชธเชฟเช‚เช—เชฒ เชชเชพเชธ:

->  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 เชชเชฐ เชœเซเช“]

เชคเซ‡เชฅเซ€, เชชเชฆเซเชงเชคเชฟ เชธเชซเชณเชคเชพเชชเซ‚เชฐเซเชตเช• เช•เชพเชฐเซเชฏ เช•เชฐเซ‡ เช›เซ‡, เชชเชฐเช‚เชคเซ เชคเซ‡เชจเซ‹ เช‰เชชเชฏเซ‹เช— เชฅเซ‹เชกเซ€ เชธเชพเชตเชงเชพเชจเซ€ เชธเชพเชฅเซ‡ เช•เชฐเชตเซ‹ เชœเซ‹เชˆเช. เช•เชพเชฐเชฃ เช•เซ‡ เชฆเชฐเซ‡เช• เชกเชฟเชฒเซ€เชŸ เช•เชฐเซ‡เชฒเชพ เชฐเซ‡เช•เซ‹เชฐเซเชก เชฎเชพเชŸเซ‡, Tid Scan เชฎเชพเช‚ เชเช• เชกเซ‡เชŸเชพ เชชเซ‡เชœ เช…เชจเซ‡ Delete เชฎเชพเช‚ เชเช• เชกเซ‡เชŸเชพ เชชเซ‡เชœ เชตเชพเช‚เชšเชตเชพเชฎเชพเช‚ เช†เชตเซ‡ เช›เซ‡.

เชธเซ‹เชฐเซเชธ: www.habr.com

DDoS เชธเซเชฐเช•เซเชทเชพ, VPS VDS เชธเชฐเซเชตเชฐ เชงเชฐเชพเชตเชคเซ€ เชธเชพเช‡เชŸเซเชธ เชฎเชพเชŸเซ‡ เชตเชฟเชถเซเชตเชธเชจเซ€เชฏ เชนเซ‹เชธเซเชŸเชฟเช‚เช— เช–เชฐเซ€เชฆเซ‹ ๐Ÿ”ฅ DDoS เชธเซเชฐเช•เซเชทเชพ, VPS VDS เชธเชฐเซเชตเชฐเซเชธ เชธเชพเชฅเซ‡ เชตเชฟเชถเซเชตเชธเชจเซ€เชฏ เชตเซ‡เชฌเชธเชพเช‡เชŸ เชนเซ‹เชธเซเชŸเชฟเช‚เช— เช–เชฐเซ€เชฆเซ‹ | ProHoster