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.
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.
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
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:
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,
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;
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