Tneħħija tar-rekords tal-klonu minn tabella mingħajr PK

Hemm sitwazzjonijiet meta għal mejda mingħajr ċavetta primarja jew xi indiċi uniku ieħor, minħabba sorveljanza, kloni kompluti ta 'rekords diġà eżistenti huma inklużi.

Tneħħija tar-rekords tal-klonu minn tabella mingħajr PK

Pereżempju, il-valuri ta 'metrika kronoloġika jinkitbu f'PostgreSQL bl-użu ta' COPY stream, u mbagħad ikun hemm falliment f'daqqa, u parti mid-dejta kompletament identika tasal mill-ġdid.

Kif teħles id-database minn kloni mhux meħtieġa?

Meta PK ma jkunx helper

L-eħfef mod huwa li tevita li sitwazzjoni bħal din isseħħ fl-ewwel lok. Per eżempju, roll PRIMARY KEY. Iżda dan mhux dejjem ikun possibbli mingħajr ma jiżdied il-volum tad-dejta maħżuna.

Pereżempju, jekk l-eżattezza tas-sistema tas-sors hija ogħla mill-eżattezza tal-qasam fid-database:

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}

Innutajt? Il-countdown minflok 00:00:02 ġie rreġistrat fid-database b'ts sekonda qabel, iżda baqa 'pjuttost validu mil-lat tal-applikazzjoni (wara kollox, il-valuri tad-dejta huma differenti!).

Naturalment tista 'tagħmel dan PK(metrika, ts) - iżda mbagħad se jkollna kunflitti ta 'inserzjoni għal data valida.

Tista 'tagħmel PK(metrika, ts, data) - iżda dan se jżid ħafna l-volum tiegħu, li aħna mhux se nużaw.

Għalhekk, l-iktar għażla korretta hija li tagħmel indiċi regolari mhux uniku (metrika, ts) u jittrattaw problemi wara l-fatt jekk jinqalgħu.

"Il-gwerra klonika bdiet"

Ġara xi tip ta 'inċident, u issa rridu neqirdu r-rekords tal-kloni mit-tabella.

Tneħħija tar-rekords tal-klonu minn tabella mingħajr PK

Ejja nmudellaw id-dejta oriġinali:

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

Hawnhekk idejna tregħddet tliet darbiet, Ctrl+V teħel, u issa...

L-ewwel, ejja nifhmu li t-tabella tagħna tista 'tkun kbira ħafna, għalhekk wara li nsibu l-kloni kollha, huwa rakkomandabbli għalina li litteralment "poke subgħajna" biex inħassru rekords speċifiċi mingħajr ma jerġgħu jfittxuhom.

U hemm mod bħal dan - dan indirizzar minn ctid, l-identifikatur fiżiku ta' rekord speċifiku.

Jiġifieri, l-ewwel nett, għandna bżonn niġbru l-ctid tar-rekords fil-kuntest tal-kontenut sħiħ tar-ringiela tat-tabella. L-iktar għażla sempliċi hija li titfa' l-linja kollha fit-test:

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

Huwa possibbli li ma titfax?Fil-prinċipju, huwa possibbli f'ħafna każijiet. Sakemm tibda tuża oqsma f'din it-tabella tipi mingħajr operatur ta' ugwaljanza:

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

Iva, naraw immedjatament li jekk ikun hemm aktar minn entrata waħda fil-firxa, dawn huma kollha kloni. Ejja nħalluhom:

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)

Għal dawk li jħobbu jikteb iqsarTista 'wkoll tikteb hekk:

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

Peress li l-valur tas-sekwenza serjali nnifisha mhuwiex interessanti għalina, aħna sempliċement thaddbuha mill-kolonni rritornati tas-subquery.

Fadal ftit xi jsir - agħmel li DELETE juża s-sett li rċevejna:

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

Ejja niċċekkjaw lilna nfusna:

Tneħħija tar-rekords tal-klonu minn tabella mingħajr PK
[ħares lejn explic.tensor.ru]

Iva, kollox huwa korrett: it-3 rekords tagħna ġew magħżula għall-unika Seq Scan tat-tabella kollha, u n-node Ħassar intuża biex tfittex dejta pass wieħed b'Tid Scan:

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

Jekk kklerjat ħafna rekords, tinsiex tmexxi VACUUM ANALYZE.

Ejja niċċekkjaw għal tabella akbar u b'numru akbar ta 'duplikati:

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;

Tneħħija tar-rekords tal-klonu minn tabella mingħajr PK
[ħares lejn explic.tensor.ru]

Għalhekk, il-metodu jaħdem b'suċċess, iżda għandu jintuża b'ċerta kawtela. Minħabba li għal kull rekord li jitħassar, hemm paġna tad-dejta waħda tinqara f'Tid Scan, u waħda f'Ħassar.

Sors: www.habr.com

Żid kumment