PK இல்லாமல் டேபிளில் இருந்து குளோன் பதிவுகளை அழிக்கிறது

சூழ்நிலைகள் உள்ளன முதன்மை விசை இல்லாத அட்டவணைக்கு அல்லது வேறு சில தனிப்பட்ட குறியீடு, மேற்பார்வையின் காரணமாக, ஏற்கனவே இருக்கும் பதிவுகளின் முழுமையான குளோன்கள் சேர்க்கப்பட்டுள்ளன.

PK இல்லாமல் டேபிளில் இருந்து குளோன் பதிவுகளை அழிக்கிறது

எடுத்துக்காட்டாக, ஒரு காலவரிசை அளவீட்டின் மதிப்புகள் ஒரு நகல் ஸ்ட்ரீமைப் பயன்படுத்தி 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 க்கு பதிலாக கவுண்டவுன் தரவுத்தளத்தில் ஒரு வினாடிக்கு முன்பே பதிவு செய்யப்பட்டது, ஆனால் பயன்பாட்டுக் கண்ணோட்டத்தில் மிகவும் செல்லுபடியாகும் (எல்லாவற்றிற்கும் மேலாக, தரவு மதிப்புகள் வேறுபட்டவை!).

நிச்சயமாக உங்களால் முடியும் பிகே(மெட்ரிக், டிஎஸ்) - ஆனால் சரியான தரவுக்கான செருகும் முரண்பாடுகளைப் பெறுவோம்.

செய்ய முடியும் பிகே(மெட்ரிக், டிஎஸ், டேட்டா) - ஆனால் இது அதன் அளவை பெரிதும் அதிகரிக்கும், அதை நாங்கள் பயன்படுத்த மாட்டோம்.

எனவே, வழக்கமான அல்லாத தனிப்பட்ட குறியீட்டை உருவாக்குவதே மிகவும் சரியான விருப்பம் (மெட்ரிக், டிஎஸ்) மற்றும் பிரச்சனைகள் எழுந்தால் அதற்குப் பிறகு சமாளிக்கவும்.

"குளோனிக் போர் தொடங்கியது"

சில வகையான விபத்து நடந்தது, இப்போது நாம் மேசையில் இருந்து குளோன் பதிவுகளை அழிக்க வேண்டும்.

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 ஐப் பார்க்கவும்]

ஆம், எல்லாம் சரியாக உள்ளது: முழு அட்டவணையின் ஒரே Seq ஸ்கேனுக்காக எங்கள் 3 பதிவுகள் தேர்ந்தெடுக்கப்பட்டன, மேலும் தரவைத் தேட நீக்கு முனை பயன்படுத்தப்பட்டது. Tid Scan உடன் ஒற்றை பாஸ்:

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

நீங்கள் நிறைய பதிவுகளை அழித்திருந்தால், வெற்றிட பகுப்பாய்வை இயக்க மறக்காதீர்கள்.

ஒரு பெரிய அட்டவணை மற்றும் அதிக எண்ணிக்கையிலான நகல்களுடன் சரிபார்ப்போம்:

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ல் படிக்கப்பட்ட தரவுப் பக்கமும், நீக்கலில் ஒன்றும் இருக்கும்.

ஆதாரம்: www.habr.com

கருத்தைச் சேர்