ಯಾವಾಗ ಸಂದರ್ಭಗಳಿವೆ ಪ್ರಾಥಮಿಕ ಕೀ ಇಲ್ಲದ ಟೇಬಲ್ಗೆ ಅಥವಾ ಕೆಲವು ಇತರ ವಿಶಿಷ್ಟ ಸೂಚ್ಯಂಕಗಳು, ಮೇಲ್ವಿಚಾರಣೆಯ ಕಾರಣದಿಂದಾಗಿ, ಈಗಾಗಲೇ ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ದಾಖಲೆಗಳ ಸಂಪೂರ್ಣ ತದ್ರೂಪುಗಳನ್ನು ಸೇರಿಸಲಾಗಿದೆ.
ಉದಾಹರಣೆಗೆ, ಕಾಲಾನುಕ್ರಮದ ಮೆಟ್ರಿಕ್ನ ಮೌಲ್ಯಗಳನ್ನು 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(ಮೆಟ್ರಿಕ್, ಟಿಎಸ್) - ಆದರೆ ನಂತರ ನಾವು ಮಾನ್ಯ ಡೇಟಾಕ್ಕಾಗಿ ಅಳವಡಿಕೆ ಸಂಘರ್ಷಗಳನ್ನು ಪಡೆಯುತ್ತೇವೆ.
ಮಾಡಬಹುದು 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 ಅನ್ನು ಸಂಗ್ರಹಿಸಬೇಕಾಗಿದೆ. ಸಂಪೂರ್ಣ ಸಾಲನ್ನು ಪಠ್ಯಕ್ಕೆ ಬಿತ್ತರಿಸುವುದು ಸರಳವಾದ ಆಯ್ಕೆಯಾಗಿದೆ:
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 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 ದಾಖಲೆಗಳನ್ನು ಸಂಪೂರ್ಣ ಟೇಬಲ್ನ ಏಕೈಕ Seq ಸ್ಕ್ಯಾನ್ಗಾಗಿ ಆಯ್ಕೆಮಾಡಲಾಗಿದೆ ಮತ್ತು ಡೇಟಾವನ್ನು ಹುಡುಕಲು ಡಿಲೀಟ್ ನೋಡ್ ಅನ್ನು ಬಳಸಲಾಗಿದೆ ಟಿಡ್ ಸ್ಕ್ಯಾನ್ನೊಂದಿಗೆ ಒಂದೇ ಪಾಸ್:
-> 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;
ಆದ್ದರಿಂದ, ವಿಧಾನವು ಯಶಸ್ವಿಯಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ, ಆದರೆ ಅದನ್ನು ಸ್ವಲ್ಪ ಎಚ್ಚರಿಕೆಯಿಂದ ಬಳಸಬೇಕು. ಏಕೆಂದರೆ ಅಳಿಸಲಾದ ಪ್ರತಿಯೊಂದು ದಾಖಲೆಗೆ, ಟಿಡ್ ಸ್ಕ್ಯಾನ್ನಲ್ಲಿ ಒಂದು ಡೇಟಾ ಪುಟವನ್ನು ಓದಲಾಗುತ್ತದೆ ಮತ್ತು ಅಳಿಸುವಿಕೆಯಲ್ಲಿ ಒಂದು ಇರುತ್ತದೆ.
ಮೂಲ: www.habr.com