A’ glanadh chlàran clone bho bhòrd gun PK

Tha suidheachaidhean ann nuair a gu bòrd gun phrìomh iuchair no clàr-amais sònraichte eile, mar thoradh air sealladh farsaing, tha clones iomlan de chlàran a tha ann mar-thà air an toirt a-steach.

A’ glanadh chlàran clone bho bhòrd gun PK

Mar eisimpleir, tha luachan meatrach eachdraidheach air an sgrìobhadh a-steach do PostgreSQL a’ cleachdadh sruth COPY, agus an uairsin bidh fàilligeadh gu h-obann, agus thig pàirt den dàta gu tur co-ionann a-rithist.

Ciamar a gheibh thu cuidhteas clones neo-riatanach bhon stòr-dàta?

Nuair nach eil PK na neach-cuideachaidh

Is e an dòigh as fhasa casg a chuir air suidheachadh mar sin sa chiad àite. Mar eisimpleir, rolla PRÌOMH PRÌOMH. Ach chan eil seo an-còmhnaidh comasach gun a bhith a 'meudachadh na tha de dhàta air a stòradh.

Mar eisimpleir, ma tha cruinneas an t-siostam stòr nas àirde na cruinneas an raoin san stòr-dàta:

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}

An do mhothaich thu? The countdown instead of 00:00:02 chaidh a chlàradh anns an stòr-dàta le ts an dàrna fear na bu thràithe, ach dh'fhuirich e gu math dligheach bho shealladh tagraidh (às deidh a h-uile càil, tha luachan an dàta eadar-dhealaichte!).

Gu dearbh faodaidh tu a dhèanamh PK (meatrach, ts) - ach an uairsin gheibh sinn còmhstri cuir a-steach airson dàta dligheach.

Is urrainn a dhèanamh PK (meatrach, ts, dàta) — ach meudaichidh so gu mòr an tomhas-lìonaidh, nach cleachd sinn.

Mar sin, is e an roghainn as ceart clàr-amais cunbhalach neo-shònraichte a dhèanamh (meatrach, ts) agus dèiligeadh ri duilgheadasan às deidh an fhìrinn ma dh’ èiricheas iad.

"Tha an cogadh clonic air tòiseachadh"

Thachair tubaist de sheòrsa air choreigin, agus a-nis feumaidh sinn na clàran clone a sgrios bhon bhòrd.

A’ glanadh chlàran clone bho bhòrd gun PK

Leig leinn an dàta tùsail a mhodail:

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)
;

An seo chrith ar làmh trì tursan, chaidh Ctrl+V an sàs, agus a-nis ...

An toiseach, tuigidh sinn gum faod am bòrd againn a bhith gu math mòr, agus mar sin às deidh dhuinn na clones gu lèir a lorg, tha e ciallach dhuinn gu litireil “ar meur a phutadh” airson cuir às. clàran sònraichte gun a bhith gan ath-sgrùdadh.

Agus tha leithid de dhòigh ann - seo a' seòladh le ctid, an aithnichear fiosaigeach de chlàr sònraichte.

Is e sin, an toiseach, feumaidh sinn ctid chlàran a chruinneachadh ann an co-theacsa susbaint iomlan an t-sreath bùird. Is e an roghainn as sìmplidh an loidhne gu lèir a thilgeil ann an teacsa:

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)"}

A bheil e comasach gun a bhith a 'tilgeil?Ann am prionnsabal, tha e comasach sa mhòr-chuid de chùisean. Gus an tòisich thu a’ cleachdadh raointean sa chlàr seo seòrsaichean às aonais gnìomhaiche co-ionannachd:

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

Yeah, chì sinn sa bhad ma tha barrachd air aon inntrigeadh san raon, is e clones a tha sin uile. Fàgaidh sinn iad dìreach:

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)

Dhaibhsan a tha dèidheil air sgrìobhadh nas giorraFaodaidh tu cuideachd a sgrìobhadh mar seo:

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

Leis nach eil luach an t-sreang sreathach fhèin inntinneach dhuinn, tha sinn dìreach ga thilgeil a-mach às na colbhan a chaidh a thilleadh den fho-cheist.

Chan eil ach beagan air fhàgail ri dhèanamh - thoir air DELETE an seata a fhuair sinn a chleachdadh:

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[]);

Feuch an dèan sinn sgrùdadh oirnn fhìn:

A’ glanadh chlàran clone bho bhòrd gun PK
[sealladh aig explain.tensor.ru]

Tha, tha a h-uile dad ceart: chaidh na clàran 3 againn a thaghadh airson an aon Seq Scan den chlàr gu lèir, agus chaidh an nód Sguab às a chleachdadh gus dàta a lorg pas singilte le Tid Scan:

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

Ma ghlanas tu mòran chlàran, na dìochuimhnich ruith VACUUM ANALYZE.

Feuch an dèan sinn sgrùdadh airson clàr nas motha agus le àireamh nas motha de dhùblaidhean:

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;

A’ glanadh chlàran clone bho bhòrd gun PK
[sealladh aig explain.tensor.ru]

Mar sin, tha an dòigh ag obair gu soirbheachail, ach feumaidh e bhith air a chleachdadh le beagan faiceallach. Oir airson a h-uile clàr a thèid a dhubhadh às, tha aon duilleag dàta air a leughadh ann an Tid Scan, agus aon ann an Sguab às.

Source: www.habr.com

Cuir beachd ann