Famafana ny rakitsoratra clone amin'ny latabatra tsy misy PK

Misy toe-javatra rehefa amin'ny latabatra tsy misy fanalahidy fototra na fanondro hafa tsy manam-paharoa, noho ny fanaraha-maso, dia ampidirina ireo clones feno amin'ireo rakitra efa misy.

Famafana ny rakitsoratra clone amin'ny latabatra tsy misy PK

Ohatra, ny soatoavin'ny metric chronological dia voasoratra ao amin'ny PostgreSQL mampiasa stream COPY, ary avy eo dia misy ny tsy fahombiazana tampoka, ary tonga indray ny ampahany amin'ny angona mitovy tanteraka.

Ahoana ny fanesorana ny angon-drakitra amin'ny klones tsy ilaina?

Rehefa tsy mpanampy i PK

Ny fomba tsotra indrindra dia ny fisorohana ny toe-javatra toy izany amin'ny voalohany. Ohatra, manorata KEY PRIMARY. Saingy tsy azo atao foana izany raha tsy mampitombo ny habetsaky ny angona voatahiry.

Ohatra, raha ambony noho ny fahamarinan'ny saha ao amin'ny tahiry ny fahamarinan'ny rafitra loharano:

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}

Voamarikao ve? Ny countdown fa tsy 00:00:02 dia voarakitra ao amin'ny angon-drakitra miaraka amin'ny ts iray segondra teo aloha, saingy nijanona ho manan-kery avy amin'ny fomba fijery fampiharana (na izany aza, ny soatoavin'ny data dia samy hafa!).

Mazava ho azy fa vitanao izany PK(metrika, ts) - fa avy eo dia hahazo fifandirana fampidirana ho an'ny angona manan-kery.

Afaka manao PK(metric, ts, data) - fa izany dia hampitombo be ny habeny, izay tsy hampiasaintsika.

Noho izany, ny safidy marina indrindra dia ny fanaovana tondro tsy mahazatra mahazatra (metrika, ts) ary miatrika olana aorian'ny zava-misy raha toa ka mitranga izany.

"Efa nanomboka ny ady klonika"

Nisy karazana loza nitranga, ary ankehitriny dia tsy maintsy handrava ny clone firaketana avy amin'ny latabatra.

Famafana ny rakitsoratra clone amin'ny latabatra tsy misy PK

Andao hatao modely ny angona tany am-boalohany:

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

In-telo nangovitra ny tananay, Ctrl+V niraikitra, ary izao...

Voalohany, andeha hojerentsika fa ny latabatra misy antsika dia mety ho lehibe be, ka rehefa avy mahita ny clones rehetra isika, dia tsara ho antsika ny "manindrona ny rantsan-tΓ nantsika" ara-bakiteny mba hamafa. firaketana manokana nefa tsy mikaroka azy ireo indray.

Ary misy fomba toy izany - izany miresaka amin'ny ctid, ny famantarana ara-batana ny rakitsoratra manokana.

Izany hoe, voalohany indrindra, dia mila manangona ny ctid ny firaketana an-tsoratra ao amin'ny toe-javatra ny votoaty feno ny latabatra andalana. Ny safidy tsotra indrindra dia ny fandefasana ny andalana manontolo ho lahatsoratra:

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

Azo atao ve ny tsy manary?Amin'ny ankapobeny dia azo atao izany amin'ny ankamaroan'ny tranga. Mandra-panombohanao mampiasa saha amin'ity tabilao ity karazana tsy misy mpandraharaha mitovy:

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

Eny, hitantsika avy hatrany fa raha misy fidirana mihoatra ny iray ao amin'ny array dia klones daholo ireo. Avelao fotsiny izy ireo:

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)

Ho an'ireo tia manoratra fohy kokoaAzonao atao koa ny manoratra azy toy izao:

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

Koa satria tsy mahaliana antsika ny sandan'ny tady serialised, dia nariantsika fotsiny avy ao amin'ny tsanganana miverina amin'ny subquery.

Kely sisa no tokony hatao - ampiasao ny DELETE amin'ny seta azonay:

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

Andeha hojerentsika ny tenantsika:

Famafana ny rakitsoratra clone amin'ny latabatra tsy misy PK
[jereo ao amin'ny explain.tensor.ru]

Eny, marina ny zava-drehetra: ny firaketanay 3 dia nofantenana ho an'ny Seq Scan tokana amin'ny latabatra manontolo, ary ny node Delete dia nampiasaina hikaroka data pass tokana miaraka amin'ny Tid Scan:

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

Raha nodiovinao ny rakitra maro, aza adino ny mihazakazaka VACUUM ANALYZE.

Andeha hojerentsika raha misy latabatra lehibe kokoa sy misy duplicate betsaka kokoa:

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;

Famafana ny rakitsoratra clone amin'ny latabatra tsy misy PK
[jereo ao amin'ny explain.tensor.ru]

Noho izany, ny fomba fiasa dia mahomby, saingy tsy maintsy ampiasaina amim-pitandremana. Satria isaky ny rakitra voafafa dia misy pejy iray ny angona vakiana ao amin'ny Tid Scan, ary iray ao amin'ny Delete.

Source: www.habr.com

Add a comment