Ku beddelashada EAV JSONB gudaha PostgreSQL

TL; DR.

Horudhac

Aan siino tusaale caadi ah oo laga yaabo inay tahay mid ka mid ah kiisaska isticmaalka ugu da'da weyn adduunka ee xogta xogta la xiriirta (database): waxaan leenahay hay'ad, waxaanan u baahanahay inaan badbaadino guryaha qaarkood (sifado) hay'adan. Laakiin xaaladaha oo dhan ma yeelan karaan isku mid oo guryaha ah, waxaana laga yaabaa in mustaqbalka lagu daro hanti badan.

Habka ugu fudud ee lagu xallin karo dhibaatadan waa in la abuuro tiir miiska xogta ee qiimihii hantida kasta, oo si fudud u buuxi kuwa loo baahan yahay tusaale ahaan cid gaar ah. Wayn! Dhibaatada la xaliyay... ilaa miiskaagu ka kooban yahay malaayiin diiwaan oo aad u baahan tahay inaad ku darto rikoor cusub.

Tixgeli qaabka EAV (Hay'adda-Sifada-Qiimaha), waxay dhacdaa marar badan. Mid ka mid ah miis wuxuu ka kooban yahay hay'ado (duubo), miis kale wuxuu ka kooban yahay magacyo hanti (sifado), iyo miis saddexaad wuxuu xiriiriyaa hay'adaha sifooyinkooda wuxuuna ka kooban yahay qiimaha sifooyinkaas cidda hadda jirta. Tani waxay ku siinaysaa awood aad ku yeelan karto noocyo kala duwan oo hanti ah oo loogu talagalay shay kala duwan, iyo sidoo kale ku dar guryaha duulista adigoon bedelin qaabka xogta.

Si kastaba ha ahaatee, ma qori lahaa qoraalkan haddii aysan jirin qaar hoos u dhac ku ah habka EVA. Marka, tusaale ahaan, si loo helo hal ama in ka badan oo leh 1 sifo kasta, 2 ku biir ayaa looga baahan yahay su'aasha: marka hore waa ku biirista miiska sifo, ka labaadna waa ku biirista miiska qiyamka. Haddii qaybtu leedahay 2 sifo, markaa 4 ku biir ayaa loo baahan yahay! Intaa waxaa dheer, dhammaan sifooyinka waxaa sida caadiga ah loo kaydiyaa sida xargaha, taas oo keenta nooca wax shubista ee natiijada iyo meesha qeeybta. Haddii aad qorto su'aalo badan, markaa tani aad bay u khasaaraysaa marka la eego isticmaalka kheyraadka.

Inkasta oo ay jiraan cilladahaas muuqda, EAV ayaa muddo dheer la isticmaalay si loo xalliyo dhibaatooyinka noocaan ah. Kuwani waxay ahaayeen cillado lama huraan ah, mana jirin si fudud oo ka wanaagsan.
Laakiin ka dib "teknoloji" cusub ayaa ka soo muuqday PostgreSQL ...

Laga bilaabo PostgreSQL 9.4, nooca xogta JSONB ayaa lagu daray si loo kaydiyo xogta binary ee JSON. In kasta oo ku kaydinta JSON qaabkan ay caadi ahaan ka qaadato boos iyo wakhti ka badan qoraalka caadiga ah ee JSON, samaynta hawlgalada ayaa aad uga dhakhso badan. JSONB sidoo kale waxay taageertaa tusmaynta, taaso ka dhigaysa waydiinta xitaa dhakhso badan.

Nooca xogta JSONB waxa ay noo ogolaataa in aan bedelno qaabka dhibka badan ee EAV annagoo ku darayna hal tiir oo JSONB ah miiska hay'ada, si weyn u fududaynaysa naqshadaynta xogta. Laakiin qaar badan ayaa ku doodaya in tani ay la socoto hoos u dhac ku yimaada wax soo saarka... Taasi waa sababta aan u qoray maqaalkan.

Dejinta kaydka xogta tijaabada

Isbarbardhiggan, waxaan ku abuuray kaydka kaydka cusub ee PostgreSQL 9.5 ee dhismaha $80 DigitalOcean Ubuntu 14.04. Ka dib markii aan dhigay qaar ka mid ah xuduudaha postgresql.conf waan orday tan qoraalka adoo isticmaalaya psql. Shaxanahan soo socda ayaa la sameeyay si loogu soo bandhigo xogta qaabka EAV:

CREATE TABLE entity ( 
  id           SERIAL PRIMARY KEY, 
  name         TEXT, 
  description  TEXT
);
CREATE TABLE entity_attribute (
  id          SERIAL PRIMARY KEY, 
  name        TEXT
);
CREATE TABLE entity_attribute_value (
  id                  SERIAL PRIMARY KEY, 
  entity_id           INT    REFERENCES entity(id), 
  entity_attribute_id INT    REFERENCES entity_attribute(id), 
  value               TEXT
);

Hoos waxaa ku yaal miis halkaas oo xogta la mid ah lagu kaydin doono, laakiin leh sifooyin ku jira tiirka nooca JSONB - guryaha.

CREATE TABLE entity_jsonb (
  id          SERIAL PRIMARY KEY, 
  name        TEXT, 
  description TEXT,
  properties  JSONB
);

Waxay u egtahay mid ka fudud, miyaanay ahayn? Kadibna waxaa lagu daray miisaska shirkadda (halbeeg & qof_jsonb) 10 milyan oo diiwaan, oo sidaas awgeed, miiska waxaa ka buuxsamay xog isku mid ah iyadoo la adeegsanayo qaabka EAV iyo habka leh tiirka JSONB - cidda_jsonb.hantiyada. Markaa, waxaanu helnay noocyo kala duwan oo xog ah oo ka mid ah dhammaan qaybaha guryaha. Tusaalaha xogta:

{
  id:          1
  name:        "Entity1"
  description: "Test entity no. 1"
  properties:  {
    color:        "red"
    lenght:       120
    width:        3.1882420
    hassomething: true
    country:      "Belgium"
  } 
}

Markaa hadda waxaanu haynaa xog isku mid ah labada doorasho. Aynu bilowno isbarbardhigga hirgelinta shaqada!

Fududee naqshadaada

Horey waxaa loo sheegay in naqshadaynta xogta xogta si weyn loo fududeeyay: hal miis, iyadoo la isticmaalayo tiir JSONB ee guryaha, halkii laga isticmaali lahaa saddex shax EAV. Laakiin sidee tani uga muuqataa codsiyada? Cusbooneysiinta hal hay'ad waxay u egtahay sidan:

-- EAV
UPDATE entity_attribute_value 
SET value = 'blue' 
WHERE entity_attribute_id = 1 
  AND entity_id = 120;

-- JSONB
UPDATE entity_jsonb 
SET properties = jsonb_set(properties, '{"color"}', '"blue"') 
WHERE id = 120;

Sida aad arki karto, codsiga ugu dambeeya uma eka mid fudud. Si loo cusboonaysiiyo qiimaha hantida ku jirta shay JSONB waa inaan isticmaalnaa shaqada jsonb_set(), oo waa in aan dhaafnaa qiimahayada cusub sida shay JSONB ah. Si kastaba ha ahaatee, uma baahnid inaan horay u sii ogaano aqoonsi kasta. Markaan eegno tusaalaha EAV, waxaan u baahanahay inaan ogaano labada qof_id iyo cidda_ sifo_id si aan u samayno cusboonaysiinta. Haddii aad rabto in aad cusboonaysiiso hanti ku jirta tiirka JSONB ee ku salaysan magaca shayga, markaa dhammaan waxa lagu sameeyaa hal xariiq oo fudud.

Hadda aynu doorano cidda aan hadda cusboonaysiinnay iyadoo ku saleysan midabkeeda cusub:

-- EAV
SELECT e.name 
FROM entity e 
  INNER JOIN entity_attribute_value eav ON e.id = eav.entity_id
  INNER JOIN entity_attribute ea ON eav.entity_attribute_id = ea.id
WHERE ea.name = 'color' AND eav.value = 'blue';

-- JSONB
SELECT name 
FROM entity_jsonb 
WHERE properties ->> 'color' = 'blue';

Waxaan u maleynayaa inaan ku heshiin karno in kan labaad uu gaaban yahay (ku biirin la'aan!), Sidaa darteedna aad loo akhriyi karo. JSONB ayaa ku guulaysatay halkan! Waxaan isticmaalnaa JSON ->> hawlwadeenka si aan u helno midabka sida qiimaha qoraalka ee shay JSONB. Waxa kale oo jirta hab labaad oo lagu gaadho isla natiijada qaabka JSONB iyadoo la isticmaalayo @> hawlwadeenka:

-- JSONB 
SELECT name 
FROM entity_jsonb 
WHERE properties @> '{"color": "blue"}';

Tani way ka sii dhib badan tahay: waxaanu eegnaa si aanu u aragno in shayga JSON ee tiirka guryaha uu ka kooban yahay shay dhinaca midig u ah hawlwadeenka @> Akhris yar, wax soo saar badan (hoos eeg).

Aynu ka dhigno isticmaalka JSONB xitaa mid sahlan marka aad u baahan tahay inaad doorato hanti badan hal mar. Tani waa halka habka JSONB uu runtii ka soo galo: waxaanu si fudud u dooranaa guryaha sida tiirar dheeraad ah natiijadayada loo dejiyay iyada oo aan loo baahnayn ku biirista:

-- JSONB 
SELECT name
  , properties ->> 'color'
  , properties ->> 'country'
FROM entity_jsonb 
WHERE id = 120;

EAV waxaad u baahan doontaa 2 ku biira guri kasta oo aad rabto inaad waydiiso. Fikradayda, su'aalaha kor ku xusan waxay muujinayaan fududaynta weyn ee naqshadaynta xogta. Fiiri tusaalooyin badan oo ku saabsan sida loo qoro weydiimaha JSONB, sidoo kale gudaha tan boostada.
Hadda waa waqtigii laga hadli lahaa waxqabadka.

Wax-soo-saarka

Si aan u barbar dhigo waxqabadka waxaan isticmaalay FALANQAYNTA SHARAX su'aalo, si loo xisaabiyo waqtiga fulinta. Weydiin kasta waxa la fuliyay ugu yaraan saddex jeer sababtoo ah qorshayuhu waxa uu qaadanayaa waqti dheer marka ugu horeysa. Marka hore waxaan ku orday weydiimaha iyada oo aan wax tilmaamo ah lahayn. Tani waxay si cad u ahayd faa'iidada JSONB, maadaama ku biirista looga baahan yahay EAV aysan isticmaali karin tusmooyinka (goobaha furaha shisheeye lama tilmaamin). Taas ka dib waxaan sameeyay tusaha 2da tiir ee furaha shisheeye ee shaxda qiimaha EAV, iyo sidoo kale tusmo GIN ee tiirka JSONB

Cusboonaysiinta xogta waxay muujisay natiijooyinka soo socda marka la eego waqtiga (ms). Ogsoonow in miisaanku yahay logarithmic:

Ku beddelashada EAV JSONB gudaha PostgreSQL

Waxaan aragnaa in JSONB ay aad uga dheer tahay (> 50000-x) EAV haddii aadan isticmaalin tusmooyinka, sababta kor lagu sheegay. Markaan ku calaamadeyno tiirarka leh furayaasha aasaasiga ah, faraqa u dhexeeyaa wuxuu ku dhow yahay inuu baaba'o, laakiin JSONB wali 1,3 jeer ayay ka dhakhso badan tahay EAV. Ogsoonow in tusaha tiirka JSONB aanu wax saamayn ah ku yeelan halkan mar haddii aynaan u isticmaalin tiirka hantida ee shuruudaha qiimaynta.

Doorashada xogta ku salaysan qiimaha hantida, waxaanu helnaa natiijooyinka soo socda (miisaanka caadiga ah):

Ku beddelashada EAV JSONB gudaha PostgreSQL

Waxaad ogaan kartaa in JSONB ay mar kale ka shaqeyso si ka dhakhso badan EAV iyada oo aan lahayn tusmooyin, laakiin marka EAV leh tusmooyin, waxay weli ka shaqeysaa si ka dhakhso badan JSONB. Laakiin markaa waxaan arkay in wakhtiyada weydiimaha JSONB ay isku mid yihiin, tani waxay igu kalliftay xaqiiqda ah in tusmooyinka GIN aysan shaqayn. Sida muuqata marka aad isticmaashid tusmada GIN ee tiir leh guryaha dadku ku badan yahay, waxa ay saamaynaysaa oo kaliya marka la isticmaalayo ka mid ah hawlwadeenka @>. Tan waxaan u adeegsaday imtixaan cusub waxayna saameyn weyn ku yeelatay waqtiga: kaliya 0,153ms! Tani waxay 15000 jeer ka dhakhso badan tahay EAV iyo 25000 jeer ka dhakhso badan hawlwadeenka ->>

Waxaan u maleynayaa inay ahayd mid degdeg ah!

Cabbirka miiska Database

Aynu is barbar dhigno cabbirka miiska labada hab. psql waxaan ku tusi karnaa cabbirka dhammaan miisaska iyo tusmooyinka iyadoo la adeegsanayo amarka dti+

Ku beddelashada EAV JSONB gudaha PostgreSQL

Habka EAV, cabbirada miisyadu waxay ku dhow yihiin 3068 MB waxayna tilmaamaysaa ilaa 3427 MB wadar ahaan 6,43 GB. Habka JSONB wuxuu isticmaalaa 1817 MB miiska iyo 318 MB ee tusmooyinka, taas oo ah 2,08 GB. Waxay soo baxdaa 3 jeer ka yar! Xaqiiqadani wax yar ayay iga yaabisay sababtoo ah waxaan ku kaydinnaa magacyada hantida shay kasta oo JSONB ah.

Laakiin weli, tirooyinka ayaa naftooda u hadla: gudaha EAV waxaan ku keydineynaa 2 furayaal qalaad halkii qiimaha sifada, taasoo keentay 8 bytes oo xog dheeri ah. Intaa waxaa dheer, EAV waxay u kaydisaa dhammaan qiyamka hantida qoraal ahaan, halka JSONB ay isticmaali doonto qiimaha nambarada iyo booleenka gudaha halka ay suurtagal tahay, taasoo keenaysa raad yar.

Natiijooyinka

Guud ahaan, waxaan filayaa in ku kaydinta guryaha hay'ada qaabka JSONB ay ka dhigi karto naqshadaynta iyo ilaalinta xogtaada mid aad u fudud. Haddii aad wado su'aalo badan, ka dib ku haysashada wax kasta oo ku jira jadwal isku mid ah sida hay'adda ayaa dhab ahaantii u shaqeyn doonta si hufan. Xaqiiqda ah in tani ay fududeyneyso isdhexgalka ka dhexeeya xogta horeyba waa dheeri, laakiin xogta natiijada ayaa 3 jeer ka yar mugga.

Sidoo kale, iyadoo lagu saleynayo imtixaannada la sameeyay, waxaan ku soo gabagabeyn karnaa in khasaaraha waxqabadku uu yahay mid aad u yar. Xaaladaha qaarkood, JSONB xitaa way ka dhakhso badan tahay EAV, taasoo ka dhigaysa mid ka sii fiican. Si kastaba ha ahaatee, cabbirkan dabcan ma daboolayo dhammaan dhinacyada (tusaale, hay'ado leh tiro aad u badan oo hanti ah, koror weyn oo ku yimid tirada hantida xogta jirta,...), markaa haddii aad hayso wax soo jeedin ah oo ku saabsan sida loo hagaajiyo. , fadlan xor u noqo inaad ku dhaafto faallooyinka!

Source: www.habr.com

Add a comment