Тоза кардани сабтҳои клон аз ҷадвал бе PK

Ҳолатҳое ҳастанд, ки ба ҷадвал бе калиди ибтидоӣ ё ягон шохиси беназири дигар, бо сабаби назорат, клонҳои пурраи сабтҳои аллакай мавҷудбуда дохил карда мешаванд.

Тоза кардани сабтҳои клон аз ҷадвал бе PK

Масалан, арзишҳои метрикаи хронологӣ бо истифода аз ҷараёни COPY дар PostgreSQL навишта мешаванд ва он гоҳ нокомии ногаҳонӣ рух медиҳад ва қисми маълумоти комилан якхела дубора ворид мешавад.

Чӣ тавр аз пойгоҳи додаҳои клонҳои нолозим халос шудан мумкин аст?

Вакте ки ПКХ ёрдамчй нест

Роҳи осонтарини пешгирӣ кардани чунин вазъият дар ҷои аввал аст. Масалан, КАЛИДИ ПРОГРАММАИ АСОСӢ. Аммо ин на ҳама вақт бе зиёд кардани ҳаҷми маълумоти захирашуда имконпазир аст.

Масалан, агар дақиқии системаи манбаъ аз саҳеҳии майдон дар пойгоҳи додаҳо баландтар бошад:

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}

Шумо пай бурдед? Бозгашт ба ҷои 00:00:02 дар пойгоҳи додаҳо бо ts як сония пештар сабт шуда буд, аммо аз нуқтаи назари барнома комилан эътибор дошт (охир, арзишҳои додаҳо гуногунанд!).

Албатта шумо метавонед ин корро кунед PK (метрик, ts) - аммо пас мо барои маълумоти дуруст ихтилофоти воридкунӣ мегирем.

Метавонед PK (метрик, ts, маълумот) — аммо ин хачми онро хеле зиёд мекунад, ки мо онро истифода намебарем.

Аз ин рӯ, варианти дурусттарин ин сохтани индекси муқаррарии ғайримуқаррарӣ мебошад (метрик, ts) ва мушкилотро пас аз он ки агар онҳо ба миён оянд, ҳал кунед.

"Ҷанги клонӣ оғоз шуд"

Як навъ садама рӯй дод ва ҳоло мо бояд сабтҳои клониро аз ҷадвал нест кунем.

Тоза кардани сабтҳои клон аз ҷадвал бе PK

Биёед маълумоти аслиро модел кунем:

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

Дар ин ҷо дасти мо се маротиба ларзид, Ctrl+V дармонд ва ҳоло...

Аввалан, биёед бифаҳмем, ки ҷадвали мо метавонад хеле калон бошад, бинобар ин пас аз пайдо кардани ҳамаи клонҳо, ба мо тавсия дода мешавад, ки аслан "ангушти худро бизанем". сабтҳои мушаххас бидуни ҷустуҷӯи дубораи онҳо.

Ва чунин роҳ вуҷуд дорад - ин муроҷиат аз ҷониби ctid, муайянкунандаи физикии сабти мушаххас.

Яъне, пеш аз ҳама, мо бояд ctid-и сабтҳоро дар заминаи мундариҷаи пурраи сатри ҷадвал ҷамъ кунем. Варианти соддатарин ин аст, ки тамоми сатрро ба матн интиқол диҳед:

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

Оё напартофтан мумкин аст?Аслан, дар аксари мавридҳо имконпазир аст. То он даме, ки шумо ба истифодаи майдонҳои ин ҷадвал шурӯъ кунед намудҳо бе оператори баробарӣ:

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

Бале, мо фавран мебинем, ки агар дар массив зиёда аз як вуруд мавҷуд бошад, ин ҳама клонҳо мебошанд. Биёед онҳоро тарк кунем:

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)

Барои онҳое, ки кӯтоҳтар навиштанро дӯст медорандШумо инчунин метавонед онро чунин нависед:

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

Азбаски арзиши худи сатри силсилавӣ барои мо ҷолиб нест, мо онро танҳо аз сутунҳои баргардонидашудаи зерпурсиш берун партоем.

Коре каме боқӣ мондааст - DELETE-ро маҷбур созед, ки маҷмӯи гирифтаамонро истифода баред:

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

Биёед худамонро тафтиш кунем:

Тоза кардани сабтҳои клон аз ҷадвал бе PK
[нигаред дар explain.tensor.ru]

Бале, ҳама чиз дуруст аст: 3 сабти мо барои ягона скани пайдарпайи тамоми ҷадвал интихоб карда шуданд ва гиреҳи Нобудкунӣ барои ҷустуҷӯи маълумот истифода шуд як гузариш бо Tid Scan:

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

Агар шумо бисёр сабтҳоро тоза карда бошед, иҷро кардани VACUUM ANALYZE-ро фаромӯш накунед.

Биёед ҷадвали калонтар ва шумораи зиёди такрорҳоро тафтиш кунем:

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;

Тоза кардани сабтҳои клон аз ҷадвал бе PK
[нигаред дар explain.tensor.ru]

Ҳамин тавр, усул бомуваффақият кор мекунад, аммо он бояд бо эҳтиёт истифода шавад. Зеро барои ҳар сабте, ки нест карда мешавад, як саҳифаи маълумот дар Tid Scan хонда мешавад ва як саҳифа дар Нест кардан.

Манбаъ: will.com

Илова Эзоҳ