መቼ ሁኔታዎች አሉ ዋና ቁልፍ ከሌለው ጠረጴዛ ጋር ወይም ሌላ የተለየ መረጃ ጠቋሚ፣ በክትትል ምክንያት፣ ቀደም ሲል የነበሩት መዝገቦች ሙሉ ክሎኖች ተካትተዋል።
ለምሳሌ ፣ የዘመን ቅደም ተከተሎች መለኪያዎች በ 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፣ ውሂብ) - ግን ይህ ድምጹን በእጅጉ ይጨምራል, እኛ የማንጠቀምበት.
ስለዚህ, በጣም ትክክለኛው አማራጭ መደበኛ ያልሆነ ኢንዴክስ ማድረግ ነው (ሜትሪክ፣ ቲ) እና ከተነሱ እውነታ በኋላ ችግሮችን መፍታት.
"የጦርነቱ ጦርነት ተጀምሯል"
አንድ ዓይነት አደጋ ተከስቷል, እና አሁን ከጠረጴዛው ላይ የክሎሎን መዝገቦችን ማጥፋት አለብን.
ዋናውን ውሂብ ሞዴል እናድርግ፡-
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 መዝገቦችን መሰብሰብ አለብን። በጣም ቀላሉ አማራጭ ሙሉውን መስመር ወደ ጽሑፍ መጣል ነው፡-
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[]);
እራሳችንን እንፈትሽ፡-
አዎ፣ ሁሉም ነገር ትክክል ነው፡ የእኛ 3 መዝገቦች ለጠቅላላው ሠንጠረዥ ሴክ ስካን ብቻ ተመርጠዋል፣ እና የ Delete node ውሂብን ለመፈለግ ጥቅም ላይ ውሏል ነጠላ ማለፊያ ከቲድ ስካን ጋር:
-> 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;
ስለዚህ, ዘዴው በተሳካ ሁኔታ ይሰራል, ነገር ግን በጥንቃቄ ጥቅም ላይ መዋል አለበት. ምክንያቱም ለእያንዳንዱ የተሰረዘ መዝገብ አንድ የዳታ ገጽ በቲድ ስካን የተነበበ እና አንድ በ Delete ውስጥ አለ።
ምንጭ: hab.com