پی کے کے بغیر ٹیبل سے کلون ریکارڈز کو صاف کرنا

ایسے حالات ہیں جب بنیادی کلید کے بغیر میز پر یا کوئی اور منفرد انڈیکس، ایک نگرانی کی وجہ سے، پہلے سے موجود ریکارڈز کے مکمل کلون شامل ہیں۔

پی کے کے بغیر ٹیبل سے کلون ریکارڈز کو صاف کرنا

مثال کے طور پر، ایک تاریخی میٹرک کی اقدار کو پوسٹگری ایس کیو ایل میں کاپی سٹریم کا استعمال کرتے ہوئے لکھا جاتا ہے، اور پھر اچانک ناکامی ہوتی ہے، اور مکمل طور پر ایک جیسے ڈیٹا کا کچھ حصہ دوبارہ آتا ہے۔

غیر ضروری کلون کے ڈیٹا بیس سے کیسے چھٹکارا حاصل کیا جائے؟

جب پی کے مددگار نہیں ہے۔

سب سے آسان طریقہ یہ ہے کہ ایسی صورت حال کو پہلے جگہ پر ہونے سے روکا جائے۔ مثال کے طور پر، بنیادی کلید کو رول کریں۔ لیکن ذخیرہ شدہ ڈیٹا کا حجم بڑھائے بغیر یہ ہمیشہ ممکن نہیں ہوتا۔

مثال کے طور پر، اگر سورس سسٹم کی درستگی ڈیٹا بیس میں فیلڈ کی درستگی سے زیادہ ہے:

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(میٹرک، ٹی ایس، ڈیٹا) - لیکن اس سے اس کا حجم بہت بڑھ جائے گا، جسے ہم استعمال نہیں کریں گے۔

اس لیے سب سے درست آپشن یہ ہے کہ باقاعدہ غیر منفرد انڈیکس بنایا جائے۔ (میٹرک، ٹی ایس) اور حقیقت کے بعد مسائل سے نمٹیں اگر وہ پیدا ہوتے ہیں۔

"کلونی جنگ شروع ہو چکی ہے"

کسی قسم کا حادثہ ہوا، اور اب ہمیں ٹیبل سے کلون ریکارڈز کو تباہ کرنا ہے۔

پی کے کے بغیر ٹیبل سے کلون ریکارڈز کو صاف کرنا

آئیے اصل ڈیٹا کا نمونہ بنائیں:

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

آئیے خود کو چیک کریں:

پی کے کے بغیر ٹیبل سے کلون ریکارڈز کو صاف کرنا
[explain.tensor.ru پر دیکھیں]

ہاں، سب کچھ درست ہے: ہمارے 3 ریکارڈ پورے ٹیبل کے واحد Seq اسکین کے لیے منتخب کیے گئے تھے، اور ڈیلیٹ نوڈ کو ڈیٹا کی تلاش کے لیے استعمال کیا گیا تھا۔ ٹڈ اسکین کے ساتھ سنگل پاس:

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

اگر آپ نے بہت سارے ریکارڈ صاف کیے ہیں، VACUUM NALYZE چلانا نہ بھولیں۔.

آئیے ایک بڑی میز اور نقل کی ایک بڑی تعداد کے ساتھ چیک کریں:

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;

پی کے کے بغیر ٹیبل سے کلون ریکارڈز کو صاف کرنا
[explain.tensor.ru پر دیکھیں]

لہذا، طریقہ کامیابی سے کام کرتا ہے، لیکن اسے کچھ احتیاط کے ساتھ استعمال کیا جانا چاہئے. کیونکہ حذف ہونے والے ہر ریکارڈ کے لیے، ٹڈ اسکین میں ایک ڈیٹا صفحہ پڑھا جاتا ہے، اور ایک ڈیلیٹ میں۔

ماخذ: www.habr.com

نیا تبصرہ شامل کریں