TL; DR: JSONB jista 'jissimplifika ħafna l-iżvilupp ta' skema tad-database mingħajr ma jissagrifikaw il-prestazzjoni tal-mistoqsija.
Introduzzjoni
Ejja nagħtu eżempju klassiku ta 'probabbilment wieħed mill-eqdem każijiet ta' użu fid-dinja ta 'database relazzjonali (database): għandna entità, u għandna bżonn insalvaw ċerti proprjetajiet (attributi) ta' din l-entità. Iżda mhux l-istanzi kollha jista 'jkollhom l-istess sett ta' proprjetajiet, u aktar proprjetajiet jistgħu jiġu miżjuda fil-futur.
L-eħfef mod biex issolvi din il-problema huwa li toħloq kolonna fit-tabella tad-database għal kull valur tal-proprjetà, u sempliċement imla dawk li huma meħtieġa għal istanza speċifika ta 'entità. Kbir! Problema solvuta... sakemm it-tabella tiegħek fiha miljuni ta' rekords u trid iżżid rekord ġdid.
Ikkunsidra l-mudell EAV (), iseħħ spiss. Tabella waħda fiha entitajiet (rekords), tabella oħra fiha ismijiet ta’ proprjetà (attributi), u t-tielet tabella tassoċja entitajiet mal-attributi tagħhom u fiha l-valur ta’ dawk l-attributi għall-entità kurrenti. Dan jagħtik l-abbiltà li jkollok settijiet differenti ta 'proprjetajiet għal oġġetti differenti, u żżid ukoll proprjetajiet fuq il-fly mingħajr ma tbiddel l-istruttura tad-database.
Madankollu, ma nkunx nikteb din il-kariga kieku ma kienx hemm xi aspetti negattivi għall-approċċ EVA. Allura, pereżempju, biex tinkiseb entità waħda jew aktar li għandhom attribut 1 kull waħda, 2 join huma meħtieġa fil-mistoqsija: l-ewwel huwa join mat-tabella tal-attributi, it-tieni huwa join mat-tabella tal-valuri. Jekk entità għandha 2 attributi, allura 4 join huma meħtieġa! Barra minn hekk, l-attributi kollha huma tipikament maħżuna bħala kordi, li jirriżulta f'ikkastjar tat-tip kemm għar-riżultat kif ukoll għall-klawżola WHERE. Jekk tikteb ħafna mistoqsijiet, allura dan huwa pjuttost ħela f'termini ta 'użu tar-riżorsi.
Minkejja dawn in-nuqqasijiet ovvji, l-EAV ilha tintuża biex issolvi dawn it-tipi ta 'problemi. Dawn kienu nuqqasijiet inevitabbli, u sempliċement ma kien hemm l-ebda alternattiva aħjar.
Imma mbagħad dehret "teknoloġija" ġdida f'PostgreSQL...
Nibda b'PostgreSQL 9.4, it-tip ta 'dejta JSONB ġie miżjud biex jaħżen id-dejta binarja JSON. Għalkemm il-ħażna ta 'JSON f'dan il-format tipikament tieħu ftit aktar spazju u ħin minn JSON b'test sempliċi, it-twettiq ta' operazzjonijiet fuqu huwa ħafna aktar mgħaġġel. JSONB jappoġġja wkoll l-indiċjar, li jagħmel il-mistoqsijiet saħansitra aktar mgħaġġel.
It-tip tad-dejta JSONB jippermettilna nissostitwixxu l-mudell EAV ingombranti billi nżidu kolonna JSONB waħda biss mat-tabella tal-entità tagħna, u tissimplifika bil-kbir id-disinn tad-database. Iżda ħafna jargumentaw li dan għandu jkun akkumpanjat minn tnaqqis fil-produttività... Huwa għalhekk li ktibt dan l-artiklu.
Twaqqif ta' database tat-test
Għal dan il-paragun, ħloqt id-database fuq installazzjoni ġdida ta 'PostgreSQL 9.5 fuq il-bini ta' $80 Ubuntu 14.04 Wara li kkonfigurajt xi parametri f'postgresql.conf, ħaddemt skript li juża psql. It-tabelli li ġejjin inħolqu biex tiġi ppreżentata d-dejta f'forma 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
);
Hawn taħt hawn tabella fejn se tinħażen l-istess data, iżda b'attributi f'kolonna tat-tip JSONB - proprjetajiet.
CREATE TABLE entity_jsonb (
id SERIAL PRIMARY KEY,
name TEXT,
description TEXT,
properties JSONB
);
Jidher ħafna aktar sempliċi, hux? Imbagħad ġie miżjud mat-tabelli tal-entitajiet (entità & entità_jsonb) 10 miljun rekord, u għaldaqstant, it-tabella kienet mimlija bl-istess data bl-użu tal-mudell EAV u l-approċċ b'kolonna JSONB - entity_jsonb.properties. Għalhekk, irċevejna diversi tipi ta 'dejta differenti fost is-sett kollu ta' proprjetajiet. Dejta ta' eżempju:
{
id: 1
name: "Entity1"
description: "Test entity no. 1"
properties: {
color: "red"
lenght: 120
width: 3.1882420
hassomething: true
country: "Belgium"
}
}Allura issa għandna l-istess data għaż-żewġ għażliet. Ejja nibdew inqabblu l-implimentazzjonijiet fuq ix-xogħol!
Issimplifika d-disinn tiegħek
Preċedentement kien iddikjarat li d-disinn tad-database kien issimplifikat ħafna: tabella waħda, billi tuża kolonna JSONB għall-proprjetajiet, minflok tuża tliet tabelli għal EAV. Imma dan kif huwa rifless fit-talbiet? L-aġġornament ta' proprjetà ta' entità waħda jidher bħal dan:
-- 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;
Kif tistgħu taraw, l-aħħar talba ma tidhirx aktar sempliċi. Biex taġġorna l-valur ta 'proprjetà f'oġġett JSONB irridu nużaw il-funzjoni , u għandha tgħaddi l-valur il-ġdid tagħna bħala oġġett JSONB. Madankollu, m'għandniex bżonn inkunu nafu l-ebda identifikatur minn qabel. Meta nħarsu lejn l-eżempju EAV, irridu nkunu nafu kemm l-entity_id kif ukoll l-entity_attribute_id sabiex inwettqu l-aġġornament. Jekk trid taġġorna proprjetà f'kolonna JSONB ibbażata fuq l-isem tal-oġġett, allura dan kollu jsir f'linja waħda sempliċi.
Issa ejja nagħżlu l-entità li għadna kemm aġġornajna abbażi tal-kulur il-ġdid tagħha:
-- 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';
Naħseb li nistgħu naqblu li t-tieni waħda hija iqsar (no join!), u għalhekk aktar tinqara. JSONB jirbaħ hawn! Aħna nużaw l-operatur JSON ->> biex niksbu l-kulur bħala valur tat-test mill-oġġett JSONB. Hemm ukoll it-tieni mod biex jinkiseb l-istess riżultat fil-mudell JSONB billi tuża l-operatur @>:
-- JSONB
SELECT name
FROM entity_jsonb
WHERE properties @> '{"color": "blue"}';
Dan huwa ftit aktar ikkumplikat: niċċekkjaw biex naraw jekk l-oġġett JSON fil-kolonna tal-proprjetajiet tiegħu fihx oġġett li jinsab fuq il-lemin tal-operatur @>. Inqas jinqara, aktar produttiv (ara hawn taħt).
Ejja nagħmlu l-użu ta' JSONB saħansitra aktar faċli meta jkollok bżonn tagħżel proprjetajiet multipli f'daqqa. Dan huwa fejn l-approċċ JSONB verament jidħol: aħna sempliċiment nagħżlu proprjetajiet bħala kolonni addizzjonali fis-sett tar-riżultati tagħna mingħajr il-ħtieġa ta 'joints:
-- JSONB
SELECT name
, properties ->> 'color'
, properties ->> 'country'
FROM entity_jsonb
WHERE id = 120;
B'EAV ser ikollok bżonn 2 join għal kull proprjetà li trid tagħmel mistoqsija. Fl-opinjoni tiegħi, il-mistoqsijiet ta 'hawn fuq juru simplifikazzjoni kbira fid-disinn tad-database. Ara aktar eżempji ta’ kif tikteb mistoqsijiet JSONB, ukoll fi post.
Issa wasal iż-żmien li nitkellmu dwar il-prestazzjoni.
Produttività
Biex tqabbel il-prestazzjoni użajt fil-mistoqsijiet, biex jiġi kkalkulat il-ħin tal-eżekuzzjoni. Kull mistoqsija ġiet esegwita mill-inqas tliet darbiet minħabba li l-pjanifikatur tal-mistoqsija jieħu aktar żmien l-ewwel darba. L-ewwel għamilt il-mistoqsijiet mingħajr ebda indiċi. Ovvjament, dan kien vantaġġ ta 'JSONB, peress li l-joints meħtieġa għal EAV ma setgħux jużaw indiċi (oqsma ewlenin barranin ma kinux indiċjati). Wara dan ħloqt indiċi fuq iż-żewġ kolonni ewlenin barranin tat-tabella tal-valur EAV, kif ukoll indiċi għal kolonna JSONB.
L-aġġornament tad-dejta wera r-riżultati li ġejjin f'termini ta 'żmien (f'ms). Innota li l-iskala hija logaritmika:

Naraw li JSONB huwa ħafna (> 50000-x) aktar mgħaġġel minn EAV jekk ma tużax indiċi, għar-raġuni ddikjarata hawn fuq. Meta aħna indiċi kolonni b'ċwievet primarji, id-differenza kważi tisparixxi, iżda JSONB għadu 1,3 darbiet aktar mgħaġġel minn EAV. Innota li l-indiċi fuq il-kolonna JSONB m'għandu l-ebda effett hawnhekk peress li aħna mhux qed nużaw il-kolonna tal-proprjetà fil-kriterji ta 'evalwazzjoni.
Għall-għażla tad-dejta bbażata fuq il-valur tal-proprjetà, irridu nġibu r-riżultati li ġejjin (skala normali):

Tista 'tinnota li JSONB jerġa' jaħdem aktar malajr minn EAV mingħajr indiċi, iżda meta EAV b'indiċi, xorta jaħdem aktar malajr minn JSONB. Imma mbagħad rajt li l-ħinijiet għall-mistoqsijiet JSONB kienu l-istess, dan wassalni għall-fatt li l-indiċi GIN ma jaħdmux. Apparentement meta tuża indiċi GIN fuq kolonna bi proprjetajiet popolati, dan jidħol fis-seħħ biss meta tuża l-operatur include @>. Użajt dan f'test ġdid u kellu impatt kbir fuq il-ħin: 0,153ms biss! Dan huwa 15000 darba aktar mgħaġġel mill-EAV u 25000 darba aktar mgħaġġel mill-operatur ->>.
Naħseb li kien mgħaġġel biżżejjed!
Daqs tat-tabella tad-database
Ejja nqabblu d-daqsijiet tat-tabella għaż-żewġ approċċi. F'psql nistgħu nuru d-daqs tat-tabelli u l-indiċi kollha bl-użu tal-kmand dti+

Għall-approċċ EAV, id-daqsijiet tal-mejda huma madwar 3068 MB u indiċi sa 3427 MB għal total ta '6,43 GB. L-approċċ JSONB juża 1817 MB għat-tabella u 318 MB għall-indiċi, li huwa 2,08 GB. Jirriżulta 3 darbiet inqas! Dan il-fatt sorpriżani ftit għaliex aħna naħżnu l-ismijiet tal-proprjetà f'kull oġġett JSONB.
Iżda xorta waħda, in-numri jitkellmu waħedhom: f'EAV aħna naħżnu ċwievet barranin 2 interi għal kull valur ta 'attribut, li jirriżultaw fi 8 bytes ta' data addizzjonali. Barra minn hekk, EAV jaħżen il-valuri tal-proprjetà kollha bħala test, filwaqt li JSONB se juża valuri numeriċi u booleani internament fejn possibbli, u dan jirriżulta f'impronta iżgħar.
Riżultati ta '
B'mod ġenerali, naħseb li l-iffrankar tal-proprjetajiet tal-entità fil-format JSONB jista 'jagħmel id-disinn u ż-żamma tad-database tiegħek ħafna aktar faċli. Jekk qed tmexxi ħafna mistoqsijiet, imbagħad iżżomm kollox fl-istess tabella bħall-entità fil-fatt taħdem b'mod aktar effiċjenti. U l-fatt li dan jissimplifika l-interazzjoni bejn id-dejta diġà huwa vantaġġ, iżda d-database li tirriżulta hija 3 darbiet iżgħar fil-volum.
Ukoll, abbażi tat-testijiet imwettqa, nistgħu nikkonkludu li t-telf fil-prestazzjoni huwa insinifikanti ħafna. F'xi każijiet, JSONB huwa saħansitra aktar mgħaġġel minn EAV, u jagħmilha saħansitra aħjar. Madankollu, dan il-punt ta’ referenza ovvjament ma jkoprix l-aspetti kollha (eż. entitajiet b’numru kbir ħafna ta’ proprjetajiet, żieda sinifikanti fin-numru ta’ proprjetajiet ta’ data eżistenti,...), allura jekk għandek xi suġġerimenti dwar kif ittejjebhom , jekk jogħġbok tħossok liberu li tħalli fil-kummenti!
Sors: www.habr.com
