Turpinot tÄmu par lielu datu plÅ«smu ierakstÄ«Å”anu, ko izvirzÄ«ja
MÄs runÄsim par TOAST iestatÄ«jumi un datu izlÄ«dzinÄÅ”ana. āVidÄjiā Ŕīs metodes neietaupÄ«s pÄrÄk daudz resursu, taÄu nemaz nemainot lietojumprogrammas kodu.
TomÄr mÅ«su pieredze Å”ajÄ ziÅÄ izrÄdÄ«jÄs ļoti produktÄ«va, jo gandrÄ«z jebkura monitoringa glabÄÅ”ana pÄc savas bÅ«tÄ«bas ir pÄrsvarÄ tikai pievienot ierakstÄ«to datu ziÅÄ. Un, ja jÅ«s domÄjat, kÄ jÅ«s varat iemÄcÄ«t datubÄzei rakstÄ«t diskÄ 200MB / s uz pusi mazÄk - lÅ«dzu zem kat.
Lielo datu mazie noslÄpumi
PÄc darba profila
Un kopÅ” tÄ laika
ApskatÄ«sim vienas tabulas struktÅ«ru, kurÄ mÄs ierakstÄm āneapstrÄdÄtusā datus - tas ir, Å”eit ir oriÄ£inÄlais teksts no žurnÄla ieraksta:
CREATE TABLE rawdata_orig(
pack -- PK
uuid NOT NULL
, recno -- PK
smallint NOT NULL
, dt -- ŠŗŠ»ŃŃ ŃŠµŠŗŃŠøŠø
date
, data -- ŃŠ°Š¼Š¾Šµ Š³Š»Š°Š²Š½Š¾Šµ
text
, PRIMARY KEY(pack, recno)
);
Tipiska zÄ«me (protams, jau sagriezta, tÄpÄc Ŕī ir sadaļas veidne), kur svarÄ«gÄkais ir teksts. Dažreiz diezgan apjomÄ«gi.
AtgÄdiniet, ka viena ieraksta āfiziskaisā lielums PG nevar aizÅemt vairÄk par vienu datu lapu, bet āloÄ£iskaisā izmÄrs ir pavisam cita lieta. Lai laukÄ ierakstÄ«tu tilpuma vÄrtÄ«bu (varchar/text/bytea), izmantojiet
PostgreSQL izmanto fiksÄtu lapas izmÄru (parasti 8 KB) un neļauj kortežÄm aptvert vairÄkas lapas. TÄpÄc nav iespÄjams tieÅ”i saglabÄt ļoti lielas lauka vÄrtÄ«bas. Lai pÄrvarÄtu Å”o ierobežojumu, lielas lauka vÄrtÄ«bas tiek saspiestas un/vai sadalÄ«tas vairÄkÄs fiziskÄs lÄ«nijÄs. Tas notiek lietotÄjam nepamanÄ«ts, un tas maz ietekmÄ lielÄko daļu servera koda. Å Ä« metode ir pazÄ«stama kÄ TOAST...
Faktiski katrai tabulai ar "potenciÄli lieliem" laukiem automÄtiski
TOAST(
chunk_id
integer
, chunk_seq
integer
, chunk_data
bytea
, PRIMARY KEY(chunk_id, chunk_seq)
);
Tas ir, ja mums ir jÄraksta virkne ar ālieluā vÄrtÄ«bu data
, tad notiks Ä«stais ieraksts ne tikai uz galveno galdu un tÄ PK, bet arÄ« uz TOAST un tÄ PK.
TOAST ietekmes samazinÄÅ”ana
Bet lielÄkÄ daļa mÅ«su ierakstu joprojÄm nav tik lieli, jÄietilpst 8KB - KÄ es varu ietaupÄ«t naudu par to?...
Šeit mums palīdz atribūts STORAGE
- PAPLAÅ INÄTS ļauj gan saspieÅ”anu, gan atseviŔķu uzglabÄÅ”anu. Å is standarta opcija lielÄkajai daļai TOAST saderÄ«go datu veidu. Vispirms tas mÄÄ£ina veikt saspieÅ”anu, pÄc tam saglabÄ to Ärpus tabulas, ja rinda joprojÄm ir pÄrÄk liela.
- GALVENÄ Ä¼auj saspiest, bet ne atseviŔķu glabÄÅ”anu. (PatiesÄ«bÄ Å”ÄdÄm kolonnÄm joprojÄm tiks veikta atseviŔķa glabÄÅ”ana, bet tikai kÄ pÄdÄjo lÄ«dzekli, ja nav citas iespÄjas samazinÄt virkni, lai tÄ ietilptu lapÄ.)
Faktiski tas ir tieÅ”i tas, kas mums ir vajadzÄ«gs tekstam - saspiediet to pÄc iespÄjas vairÄk un, ja tas vispÄr neder, ielieciet to TOAST. To var izdarÄ«t tieÅ”i lidojuma laikÄ ar vienu komandu:
ALTER TABLE rawdata_orig ALTER COLUMN data SET STORAGE MAIN;
KÄ novÄrtÄt efektu
TÄ kÄ datu plÅ«sma mainÄs katru dienu, mÄs nevaram salÄ«dzinÄt absolÅ«tos skaitļus, bet gan relatÄ«vÄ izteiksmÄ mazÄka daļa MÄs to pierakstÄ«jÄm TOAST ā jo labÄk. Bet Å”eit pastÄv briesmas - jo lielÄks ir katra atseviŔķa ieraksta āfiziskaisā apjoms, jo āplaÅ”Äksā kļūst rÄdÄ«tÄjs, jo mums ir jÄaptver vairÄk datu lapu.
Sadaļa pirms izmaiÅÄm:
heap = 37GB (39%)
TOAST = 54GB (57%)
PK = 4GB ( 4%)
Sadaļa pÄc izmaiÅÄm:
heap = 37GB (67%)
TOAST = 16GB (29%)
PK = 2GB ( 4%)
PatiesÄ«bÄ mÄs sÄka rakstÄ«t TOAST 2 reizes retÄk, kas izlÄdÄja ne tikai disku, bet arÄ« centrÄlo procesoru:
AtzÄ«mÄÅ”u, ka esam kļuvuÅ”i mazÄki arÄ« diska ālasÄ«Å”anÄā, ne tikai ārakstÄ«Å”anÄā - tÄ kÄ, ievietojot ierakstu tabulÄ, mums ir ājÄizlasaā arÄ« daļa no katra indeksa koka, lai noteiktu tÄ nÄkotnes pozÄ«cija tajÄs.
KurŔ var labi dzīvot, izmantojot PostgreSQL 11
PÄc atjauninÄÅ”anas uz PG11, mÄs nolÄmÄm turpinÄt ānoskaÅotā TOAST un pamanÄ«jÄm, ka sÄkot ar Å”o versiju parametrs toast_tuple_target
TOAST apstrÄdes kods tiek aktivizÄts tikai tad, ja tabulÄ saglabÄjamÄs rindas vÄrtÄ«ba ir lielÄka par TOAST_TUPLE_THRESHOLD baitiem (parasti 2 KB). TOAST kods saspiedÄ«s un/vai pÄrvietos lauka vÄrtÄ«bas no tabulas, lÄ«dz rindas vÄrtÄ«ba kļūs mazÄka par TOAST_TUPLE_TARGET baitiem (mainÄ«ga vÄrtÄ«ba, arÄ« parasti 2 KB) vai arÄ« izmÄru nevarÄs samazinÄt.
MÄs nolÄmÄm, ka mÅ«su rÄ«cÄ«bÄ esoÅ”ie dati parasti ir āļoti Ä«siā vai āļoti gariā, tÄpÄc nolÄmÄm aprobežoties ar minimÄlo iespÄjamo vÄrtÄ«bu:
ALTER TABLE rawplan_orig SET (toast_tuple_target = 128);
ApskatÄ«sim, kÄ jaunie iestatÄ«jumi ietekmÄja diska ielÄdi pÄc atkÄrtotas konfigurÄÅ”anas:
Nav slikti! VidÄji rinda uz disku ir samazinÄjusies aptuveni 1.5 reizes, un disks ir āaizÅemtsā par 20 procentiem! Bet varbÅ«t tas kaut kÄ ietekmÄja centrÄlo procesoru?
Vismaz sliktÄk nekļuva. Lai gan ir grÅ«ti spriest, vai pat Å”Ädi apjomi joprojÄm nevar paaugstinÄt vidÄjo CPU slodzi 5%.
Mainot terminu vietas, summa... mainÄs!
KÄ jÅ«s zinÄt, penss ietaupa rubli, un ar mÅ«su uzglabÄÅ”anas apjomiem tas ir aptuveni 10 TB/mÄnesÄ« pat neliela optimizÄcija var dot labu peļÅu. TÄpÄc mÄs pievÄrsÄm uzmanÄ«bu mÅ«su datu fiziskajai struktÅ«rai ā kÄ tieÅ”i āsakrautiā lauki ieraksta iekÅ”pusÄ katrÄ no tabulÄm.
Jo tÄpÄc
Daudzas arhitektÅ«ras nodroÅ”ina datu izlÄ«dzinÄÅ”anu uz maŔīnu vÄrdu robežÄm. PiemÄram, 32 bitu x86 sistÄmÄ veseli skaitļi (vesela skaitļa tips, 4 baiti) tiks lÄ«dzinÄti uz 4 baitu vÄrda robežas, kÄ arÄ« dubultÄs precizitÄtes peldoÅ”Ä komata skaitļi (dubultÄs precizitÄtes peldoÅ”Ä komata, 8 baiti). Un 64 bitu sistÄmÄ dubultÄs vÄrtÄ«bas tiks saskaÅotas ar 8 baitu vÄrdu robežÄm. Tas ir vÄl viens nesaderÄ«bas iemesls.
LÄ«dzinÄÅ”anas dÄļ tabulas rindas lielums ir atkarÄ«gs no lauku secÄ«bas. Parasti Å”is efekts nav Ä«paÅ”i pamanÄms, bet dažos gadÄ«jumos tas var izraisÄ«t ievÄrojamu izmÄru palielinÄÅ”anos. PiemÄram, ja sajaucat char(1) un veselu skaitļu laukus, starp tiem parasti tiek iztÄrÄti 3 baiti.
SÄksim ar sintÄtiskiem modeļiem:
SELECT pg_column_size(ROW(
'0000-0000-0000-0000-0000-0000-0000-0000'::uuid
, 0::smallint
, '2019-01-01'::date
));
-- 48 Š±Š°Š¹Ń
SELECT pg_column_size(ROW(
'2019-01-01'::date
, '0000-0000-0000-0000-0000-0000-0000-0000'::uuid
, 0::smallint
));
-- 46 Š±Š°Š¹Ń
No kurienes pirmajÄ gadÄ«jumÄ radÄs pÄris papildu baiti? Tas ir vienkÄrÅ”i - 2 baitu mazÄ daļa ir izlÄ«dzinÄta uz 4 baitu robežas pirms nÄkamÄ lauka, un kad tas ir pÄdÄjais, tad nav nekÄ un nav jÄlÄ«dzina.
TeorÄtiski viss ir kÄrtÄ«bÄ un var pÄrkÄrtot laukus kÄ gribi. PÄrbaudÄ«sim to uz reÄliem datiem, izmantojot vienas tabulas piemÄru, kuras ikdienas sadaļa aizÅem 10-15 GB.
SÄkotnÄjÄ struktÅ«ra:
CREATE TABLE public.plan_20190220
(
-- Š£Š½Š°ŃŠ»ŠµŠ“Š¾Š²Š°Š½Š° from table plan: pack uuid NOT NULL,
-- Š£Š½Š°ŃŠ»ŠµŠ“Š¾Š²Š°Š½Š° from table plan: recno smallint NOT NULL,
-- Š£Š½Š°ŃŠ»ŠµŠ“Š¾Š²Š°Š½Š° from table plan: host uuid,
-- Š£Š½Š°ŃŠ»ŠµŠ“Š¾Š²Š°Š½Š° from table plan: ts timestamp with time zone,
-- Š£Š½Š°ŃŠ»ŠµŠ“Š¾Š²Š°Š½Š° from table plan: exectime numeric(32,3),
-- Š£Š½Š°ŃŠ»ŠµŠ“Š¾Š²Š°Š½Š° from table plan: duration numeric(32,3),
-- Š£Š½Š°ŃŠ»ŠµŠ“Š¾Š²Š°Š½Š° from table plan: bufint bigint,
-- Š£Š½Š°ŃŠ»ŠµŠ“Š¾Š²Š°Š½Š° from table plan: bufmem bigint,
-- Š£Š½Š°ŃŠ»ŠµŠ“Š¾Š²Š°Š½Š° from table plan: bufdsk bigint,
-- Š£Š½Š°ŃŠ»ŠµŠ“Š¾Š²Š°Š½Š° from table plan: apn uuid,
-- Š£Š½Š°ŃŠ»ŠµŠ“Š¾Š²Š°Š½Š° from table plan: ptr uuid,
-- Š£Š½Š°ŃŠ»ŠµŠ“Š¾Š²Š°Š½Š° from table plan: dt date,
CONSTRAINT plan_20190220_pkey PRIMARY KEY (pack, recno),
CONSTRAINT chck_ptr CHECK (ptr IS NOT NULL),
CONSTRAINT plan_20190220_dt_check CHECK (dt = '2019-02-20'::date)
)
INHERITS (public.plan)
Sadaļa pÄc kolonnu secÄ«bas maiÅas - precÄ«zi tie paÅ”i lauki, tikai cita secÄ«ba:
CREATE TABLE public.plan_20190221
(
-- Š£Š½Š°ŃŠ»ŠµŠ“Š¾Š²Š°Š½Š° from table plan: dt date NOT NULL,
-- Š£Š½Š°ŃŠ»ŠµŠ“Š¾Š²Š°Š½Š° from table plan: ts timestamp with time zone,
-- Š£Š½Š°ŃŠ»ŠµŠ“Š¾Š²Š°Š½Š° from table plan: pack uuid NOT NULL,
-- Š£Š½Š°ŃŠ»ŠµŠ“Š¾Š²Š°Š½Š° from table plan: recno smallint NOT NULL,
-- Š£Š½Š°ŃŠ»ŠµŠ“Š¾Š²Š°Š½Š° from table plan: host uuid,
-- Š£Š½Š°ŃŠ»ŠµŠ“Š¾Š²Š°Š½Š° from table plan: apn uuid,
-- Š£Š½Š°ŃŠ»ŠµŠ“Š¾Š²Š°Š½Š° from table plan: ptr uuid,
-- Š£Š½Š°ŃŠ»ŠµŠ“Š¾Š²Š°Š½Š° from table plan: bufint bigint,
-- Š£Š½Š°ŃŠ»ŠµŠ“Š¾Š²Š°Š½Š° from table plan: bufmem bigint,
-- Š£Š½Š°ŃŠ»ŠµŠ“Š¾Š²Š°Š½Š° from table plan: bufdsk bigint,
-- Š£Š½Š°ŃŠ»ŠµŠ“Š¾Š²Š°Š½Š° from table plan: exectime numeric(32,3),
-- Š£Š½Š°ŃŠ»ŠµŠ“Š¾Š²Š°Š½Š° from table plan: duration numeric(32,3),
CONSTRAINT plan_20190221_pkey PRIMARY KEY (pack, recno),
CONSTRAINT chck_ptr CHECK (ptr IS NOT NULL),
CONSTRAINT plan_20190221_dt_check CHECK (dt = '2019-02-21'::date)
)
INHERITS (public.plan)
KopÄjo sadaļas apjomu nosaka āfaktuā skaits un tas ir atkarÄ«gs tikai no ÄrÄjiem procesiem, tÄpÄc sadalÄ«sim kaudzes lielumu (pg_relation_size
) pÄc tajÄ esoÅ”o ierakstu skaita - tas ir, mÄs iegÅ«stam faktiski saglabÄtÄ ieraksta vidÄjais lielums:
MÄ«nus 6% tilpuma, Lieliski!
Bet viss, protams, nav tik rožaini - galu galÄ, indeksos mÄs nevaram mainÄ«t lauku secÄ«buun tÄpÄc āvispÄrā (pg_total_relation_size
) ...
...joprojÄm arÄ« Å”eit ietaupÄ«ti 1.5%nemainot nevienu koda rindiÅu. JÄ jÄ!
Es atzÄ«mÄju, ka iepriekÅ” minÄtÄ lauku sakÄrtoÅ”anas iespÄja nav tÄ, ka tÄ ir optimÄlÄkÄ. TÄpÄc, ka estÄtisku apsvÄrumu dÄļ nevÄlaties ānoplÄstā dažus lauku blokus - piemÄram, pÄris (pack, recno)
, kas ir Ŕīs tabulas PK.
KopumÄ lauku āminimÄlÄā izvietojuma noteikÅ”ana ir diezgan vienkÄrÅ”s ābrutÄla spÄkaā uzdevums. TÄpÄc no saviem datiem varat iegÅ«t vÄl labÄkus rezultÄtus nekÄ mÅ«sÄjie ā izmÄÄ£iniet!
Avots: www.habr.com