Berdewamkirina mijara tomarkirina herikên daneyên mezin ên ku ji hêla ve hatî rakirin
Em ê biaxivin Mîhengên TOAST û berhevkirina daneyê. "Bi navînî," van rêbazan dê gelek çavkaniyan xilas nekin, lê bêyî ku koda serîlêdanê bi tevahî biguherînin.
Lêbelê, ezmûna me di vî warî de pir hilberîner derket, ji ber ku hilanîna hema hema her çavdêriyê ji hêla cewherê xwe ve ye bi piranî pêvek-tenê di warê daneyên tomarkirî de. Û heke hûn meraq dikin ka hûn çawa dikarin databasê fêrî nivîsandina dîskê bikin 200MB / s nîv bi qasî - ji kerema xwe binê pisîkê.
Sirên piçûk ên daneyên mezin
Li gorî profîla kar
Since ji ber ku
Ka em li avahiya yek ji tabloyên ku em daneya "xew" tê de dinivîsin binêrin - ango, li vir nivîsa orîjînal ji têketina têketinê ye:
CREATE TABLE rawdata_orig(
pack -- PK
uuid NOT NULL
, recno -- PK
smallint NOT NULL
, dt -- ключ секции
date
, data -- самое главное
text
, PRIMARY KEY(pack, recno)
);
Nîşanek tîpîk (bê guman, jixwe veqetandî ye, ji ber vê yekê ev şablonek beşê ye), ku ya herî girîng nivîs e. Carinan pir mezin.
Bînin bîra xwe ku mezinahiya "fizîkî" ya yek tomarek di PG-ê de nikare zêdetirî yek rûpelek daneyê dagir bike, lê mezinahiya "mantiqî" mijarek bi tevahî cûda ye. Ji bo nivîsandina nirxek volumetric (varchar/text/bytea) li zeviyek, bikar bînin
PostgreSQL mezinahiyek rûpelek sabît (bi gelemperî 8 KB) bikar tîne, û rê nade ku tuples çend rûpelan vegerînin. Ji ber vê yekê, ne gengaz e ku meriv rasterast nirxên zeviyê pir mezin hilîne. Ji bo derbaskirina vê sînorkirinê, nirxên zeviyê yên mezin li ser gelek xêzên laşî têne berhev kirin û/an parçe kirin. Ev ji hêla bikarhêner ve nayê dîtin û bandorek piçûk li ser piraniya koda serverê dike. Ev rêbaz wekî TOAST tê zanîn ...
Bi rastî, ji bo her tabloya bi qadên "bi potansiyel mezin", bixweber
TOAST(
chunk_id
integer
, chunk_seq
integer
, chunk_data
bytea
, PRIMARY KEY(chunk_id, chunk_seq)
);
Ango ger divê em rêzek bi nirxek “mezin” binivîsin data
, wê hingê tomarkirina rastîn dê çêbibe ne tenê ji maseya sereke û PK-ya wê, lê di heman demê de ji TOAST û PK-ya wê re jî.
Kêmkirina bandora TOAST
Lê piraniya tomarên me hîn ne ew qas mezin in, divê di 8KB de cih bigire - Ez çawa dikarim li ser vê yekê pereyan teserûf bikim?..
Li vir taybetmendî tê alîkariya me STORAGE
- BİXWÎNE hem compression û hem jî hilanîna veqetandî dihêle. Ev option standard ji bo piraniya celebên daneya lihevhatî TOAST. Ew pêşî hewl dide ku berhevkirinê pêk bîne, dûv re wê li derveyî maseyê hilîne ger rêz hîn jî pir mezin be.
- DESTÊ destûrê dide kompresê lê ne hilanîna veqetandî. (Bi rastî, hilanîna veqetandî dê hîn jî ji bo stûnên weha were kirin, lê tenê wek çareya dawî, gava ku rêyek din tune ku rêzê piçûk bike da ku ew li ser rûpelê bicîh bibe.)
Bi rastî, tiştê ku em ji bo nivîsê hewce ne ev e - bi qasî ku gengaz be wê biqelînin, û heke ew qet neqewime, wê têxin nav TOAST. Ev dikare rasterast li ser firînê, bi yek fermanê were kirin:
ALTER TABLE rawdata_orig ALTER COLUMN data SET STORAGE MAIN;
Meriv çawa bandorê dinirxîne
Ji ber ku herikîna daneyê her roj diguhere, em nekarin hejmarên bêkêmasî, lê bi şertên nisbî bidin ber hev para piçûktir Me ew di TOAST de nivîsand - ew qas çêtir. Lê li vir xeterek heye - her ku hejmûna "fizîkî" ya her tomarek kesane mezintir bibe, index "berfireh" dibe, ji ber ku pêdivî ye ku em bêtir rûpelên daneyê veşêrin.
Liq berî guhertinan:
heap = 37GB (39%)
TOAST = 54GB (57%)
PK = 4GB ( 4%)
Liq piştî guhertinan:
heap = 37GB (67%)
TOAST = 16GB (29%)
PK = 2GB ( 4%)
Bi rastî, em 2 caran kêmtir dest bi nivîsandina TOAST kir, ku ne tenê dîskê, lê di heman demê de CPU jî dakêşand:
Ez ê bala xwe bidim ku em di "xwendina" dîskê de jî piçûktir bûne, ne tenê "nivîsandin" - ji ber ku dema tomarek têxin nav tabloyek, di heman demê de pêdivî ye ku em beşek ji dara her nîşanekê jî "bixwînin" da ku wê diyar bikin. helwesta pêşerojê di wan de.
Kî dikare li ser PostgreSQL 11 baş bijî
Piştî nûvekirina PG11, me biryar da ku em "tuning" TOAST bidomînin û me dît ku ji vê guhertoyê dest pê dike parametre toast_tuple_target
Koda pêvajoyê ya TOAST tenê dema ku nirxa rêzê ya ku di tabloyê de were hilanîn ji TOAST_TUPLE_THRESHOLD bytes (bi gelemperî 2 KB) mezintir be, dişewite. Koda TOAST dê nirxên zeviyê ji tabloyê biqelişîne û/an bikişîne heya ku nirxa rêzê ji TOAST_TUPLE_TARGET bytes (nirxa guhêrbar, di heman demê de bi gelemperî 2 KB) kêmtir bibe an mezinahî neyê kêm kirin.
Me biryar da ku daneyên ku em bi gelemperî hene an "pir kurt" an "pir dirêj" in, ji ber vê yekê me biryar da ku em xwe bi nirxa herî hindiktirîn sînordar bikin:
ALTER TABLE rawplan_orig SET (toast_tuple_target = 128);
Ka em bibînin ka mîhengên nû çawa bandor li barkirina dîskê piştî veavakirinê kir:
Xerab nîne! Navoser rêza dîskê kêm bûye Nêzîkî 1.5 carî, û dîskê "mijûl" ji sedî 20 e! Lê dibe ku ev bi rengek bandor li CPU-yê kir?
Qe nebe ew xerabtir nebû. Her çend, dijwar e ku meriv dadbar bike ger cildên weha hîn jî nekarin barkirina navînî ya CPU-yê bilindtir bikin 5%.
Bi guherandina cîhên terman, hevok... diguhere!
Wekî ku hûn dizanin, quruşek rubleyek xilas dike, û bi cildên hilanîna me re ew e 10TB/mehê tewra xweşbîniyek piçûk jî dikare qezencek baş bide. Ji ber vê yekê, me bala xwe da avahiya fizîkî ya daneyên xwe - çawa bi rastî Zeviyên "lihevkirî" di hundurê tomarê de her yek ji tabloyan.
Ji ber ku ji ber
Gelek mîmarî li ser sînorên peyva makîneyê lihevhatina daneyê peyda dikin. Mînakî, li ser pergalek 32-bit x86, hejmarên bêkêmasî (cûreya jimare, 4 byte) dê li ser sînorê peyva 4-byte bêne rêz kirin, her weha dê jimareyên xala herikînê ya rast du qat bikin (xala herikandinê ya ducarî, 8 byte). Û li ser pergalek 64-bit, nirxên ducar dê li ser sînorên peyvan 8-byte bêne rêz kirin. Ev jî sedemeke din a lihevnekirinê ye.
Ji ber lihevkirinê, mezinahiya rêzek tabloyê bi rêza qadan ve girêdayî ye. Bi gelemperî ev bandor ne pir xuya ye, lê di hin rewşan de ew dikare bibe sedema zêdebûna mezinbûnê. Mînakî, heke hûn zeviyên char (1) û jimarek tevhev tevlihev bikin, dê bi gelemperî di navbera wan de 3 bytes winda bibin.
Ka em bi modelên sentetîk dest pê bikin:
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 байт
Di doza yekem de çend bytên zêde ji ku derketin? Ew hêsan e - 2-byte piçûk li ser sînorê 4-byte li hev kirin berî qada paşîn, û gava ku ew ya paşîn be, tiştek û ne hewce ye ku meriv hevûdu bike.
Di teoriyê de, her tişt baş e û hûn dikarin zeviyan wekî ku hûn dixwazin ji nû ve saz bikin. Ka em bi mînaka yek ji tabloyan, beşa rojane ya ku 10-15 GB digire, li ser daneyên rastîn kontrol bikin.
Struktura destpêkê:
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)
Beşa piştî guheztina rêzika stûnê - tam heman zeviyan, tenê rêzek cûda:
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)
Hêjmara giştî ya beşê ji hêla hejmara "rastiyan" ve tête diyar kirin û tenê bi pêvajoyên derveyî ve girêdayî ye, ji ber vê yekê em ê mezinahiya girikê dabeş bikin (pg_relation_size
) bi hejmara tomarên tê de - ango, em distînin mezinahiya navîn ya qeyda hilandî ya rastîn:
Minus 6% volume, Ecêb!
Lê her tişt, bê guman, ne ew qas gul e - paşî, di indexan de em nikarin rêza qadan biguherînin, û ji ber vê yekê "bi gelemperî" (pg_total_relation_size
) ...
... hê jî li vir xilas 1.5%bêyî ku yek rêzek kodê biguhezîne. Erê, belê!
Ez bala xwe didim ku vebijarka jorîn ji bo sazkirina zeviyan ne rastiyek e ku ew çêtirîn çêtirîn e. Ji ber ku hûn naxwazin hin blokên zeviyan ji ber sedemên estetîkî "çirînin" - mînakî, cotek (pack, recno)
, ku ji bo vê tabloyê PK ye.
Bi gelemperî, destnîşankirina rêza "kêmtirîn" a zeviyan karekî "hêza hov" pir hêsan e. Ji ber vê yekê, hûn dikarin ji daneyên xwe ji ya me hîn çêtir encamên xwe bistînin - wê biceribînin!
Source: www.habr.com