Taifid chlónála a ghlanadh ó tábla gan PK

Tá cásanna nuair a chuig tábla gan eochair phríomha nó innéacs uathúil éigin eile, mar gheall ar fhormhaoirseacht, áirítear clóin iomlána de thaifid atá ann cheana féin.

Taifid chlónála a ghlanadh ó tábla gan PK

Mar shampla, scríobhtar luachanna méadrach cróineolaíoch isteach i PostgreSQL ag baint úsáide as sruth COPY, agus ansin tá teip tobann ann, agus tagann cuid de na sonraí go hiomlán comhionann arís.

Conas fáil réidh leis an mbunachar sonraí de chlóin neamhriachtanach?

Nuair nach cúntóir é PK

Is é an bealach is éasca chun a leithéid de chás a chosc ó tharla sa chéad áit. Mar shampla, rolla PRIMARY EOCHAIR. Ach ní féidir é seo a dhéanamh i gcónaí gan an méid sonraí stóráilte a mhéadú.

Mar shampla, má tá cruinneas an chórais foinse níos airde ná cruinneas an réimse sa bhunachar sonraí:

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}

Ar thug tú faoi deara? Taifeadadh an comhaireamh síos in ionad 00:00:02 sa bhunachar sonraí le ts an dara háit níos luaithe, ach d'fhan sé sách bailí ó thaobh iarratais (tar éis an tsaoil, tá na luachanna sonraí difriúil!).

Ar ndóigh, is féidir leat é a dhéanamh PK(méadrach, ts) - ach ansin gheobhaidh muid coinbhleachtaí ionchuir le haghaidh sonraí bailí.

An féidir é a dhéanamh PK(méadrach, ts, sonraí) - ach méadóidh sé seo go mór a toirt, rud nach n-úsáidfimid.

Mar sin, is é an rogha is ceart ná innéacs rialta neamh-uathúil a dhéanamh (méadrach, ts) agus déileáil le fadhbanna tar éis an fhíric má thagann siad chun cinn.

"Tá an cogadh clonic tosaithe"

Tharla timpiste de chineál éigin, agus anois ní mór dúinn na taifid chlón a scriosadh ón tábla.

Taifid chlónála a ghlanadh ó tábla gan PK

Déanaimis na sonraí bunaidh a shamhaltú:

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

Anseo tháinig crith ar ár lámh trí huaire, chuaigh Ctrl+V i bhfostú, agus anois...

Gcéad dul síos, tuigimid gur féidir lenár mbord a bheith an-mhór, mar sin tar éis dúinn na clóin go léir a aimsiú, tá sé inmholta dúinn "ár méar a bhrú" go litriúil le scriosadh. taifid ar leith gan iad a athchuardach.

Agus tá a leithéid de bhealach - seo ag seoladh ag ctid, aitheantóir fisiciúil taifid ar leith.

Is é sin, ar an gcéad dul síos, ní mór dúinn cid na dtaifead a bhailiú i gcomhthéacs ábhar iomlán an tsraith tábla. Is é an rogha is simplí an líne iomlán a chaitheamh isteach i dtéacs:

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

An bhfuil sé indéanta gan a chaitheamh?I bprionsabal, is féidir i bhformhór na gcásanna. Go dtí go dtosaíonn tú ag baint úsáide as réimsí sa tábla seo cineálacha gan oibreoir comhionannais:

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

Sea, feicimid láithreach má tá níos mó ná iontráil amháin san eagar, gur clóin iad seo go léir. Fágaimis iad:

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)

Dóibh siúd ar mhaith leo scríobh níos giorraIs féidir leat é a scríobh mar seo freisin:

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

Ós rud é nach bhfuil luach na sreinge sraitheach féin suimiúil dúinn, níor ghá dúinn ach é a chaitheamh amach as na colúin a cuireadh ar ais den fhocheist.

Níl ach beagán fágtha le déanamh - bain úsáid as DELETE as an tacar a fuaireamar:

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

Déanaimis seiceáil orainn féin:

Taifid chlónála a ghlanadh ó tábla gan PK
[féach ar explain.tensor.ru]

Sea, tá gach rud ceart: roghnaíodh ár 3 thaifead don aon Scanadh Seq amháin den tábla iomlán, agus úsáideadh an nód Scrios chun sonraí a chuardach pas singil le Tid Scan:

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

Má ghlan tú go leor taifead, ná déan dearmad ANAILÍS FOLÚCHÁIN a rith.

Déanaimis seiceáil le haghaidh tábla níos mó agus le líon níos mó dúblaigh:

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;

Taifid chlónála a ghlanadh ó tábla gan PK
[féach ar explain.tensor.ru]

Mar sin, oibríonn an modh go rathúil, ach ní mór é a úsáid le roinnt rabhadh. Mar gheall ar gach taifead a scriostar, tá leathanach sonraí amháin léite i Tid Scan, agus ceann eile i Scrios.

Foinse: will.com

Add a comment