PK ከሌለው የክሎሎን መዝገቦችን ከጠረጴዛ ላይ በማጽዳት ላይ

መቼ ሁኔታዎች አሉ ዋና ቁልፍ ከሌለው ጠረጴዛ ጋር ወይም ሌላ የተለየ መረጃ ጠቋሚ፣ በክትትል ምክንያት፣ ቀደም ሲል የነበሩት መዝገቦች ሙሉ ክሎኖች ተካትተዋል።

PK ከሌለው የክሎሎን መዝገቦችን ከጠረጴዛ ላይ በማጽዳት ላይ

ለምሳሌ ፣ የዘመን ቅደም ተከተሎች መለኪያዎች በ PostgreSQL ውስጥ የ COPY ዥረት በመጠቀም ይፃፋሉ ፣ እና ከዚያ ድንገተኛ ውድቀት አለ ፣ እና የፍፁም ተመሳሳይ መረጃ ክፍል እንደገና ይመጣል።

የውሂብ ጎታውን አላስፈላጊ ክሎኖችን እንዴት ማስወገድ እንደሚቻል?

PK ረዳት በማይሆንበት ጊዜ

በጣም ቀላሉ መንገድ እንዲህ ዓይነቱ ሁኔታ በመጀመሪያ ደረጃ እንዳይከሰት መከላከል ነው. ለምሳሌ፣ የመጀመሪያ ደረጃ ቁልፍን ጥቅልል። ነገር ግን ይህ የተከማቸ ውሂብ መጠን ሳይጨምር ሁልጊዜ የሚቻል አይደለም.

ለምሳሌ፣ የምንጭ ስርዓቱ ትክክለኛነት በመረጃ ቋቱ ውስጥ ካለው የመስክ ትክክለኛነት ከፍ ያለ ከሆነ፡-

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

እራሳችንን እንፈትሽ፡-

PK ከሌለው የክሎሎን መዝገቦችን ከጠረጴዛ ላይ በማጽዳት ላይ
[ማብራሪያውን ይመልከቱ.tensor.ru]

አዎ፣ ሁሉም ነገር ትክክል ነው፡ የእኛ 3 መዝገቦች ለጠቅላላው ሠንጠረዥ ሴክ ስካን ብቻ ተመርጠዋል፣ እና የ Delete node ውሂብን ለመፈለግ ጥቅም ላይ ውሏል ነጠላ ማለፊያ ከቲድ ስካን ጋር:

->  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 ከሌለው የክሎሎን መዝገቦችን ከጠረጴዛ ላይ በማጽዳት ላይ
[ማብራሪያውን ይመልከቱ.tensor.ru]

ስለዚህ, ዘዴው በተሳካ ሁኔታ ይሰራል, ነገር ግን በጥንቃቄ ጥቅም ላይ መዋል አለበት. ምክንያቱም ለእያንዳንዱ የተሰረዘ መዝገብ አንድ የዳታ ገጽ በቲድ ስካን የተነበበ እና አንድ በ Delete ውስጥ አለ።

ምንጭ: hab.com

አስተያየት ያክሉ