TL;DR: Faodaidh JSONB leasachadh sgeama stòr-dĂ ta a dhèanamh gu mòr nas sĂŹmplidhe gun a bhith aâ ĂŹobairt coileanadh cheistean.
Ro-rĂ dh
Gabhamaid eisimpleir clasaigeach, is dòcha aon de na cĂšisean cleachdaidh as sine ann an saoghal stòran-dĂ ta dĂ imheil: tha eintiteas againn, agus feumaidh sinn feartan sònraichte den eintiteas seo a stòradh. Ach is dòcha nach bi an aon sheata de fheartan aig a h-uile eisimpleir, agus dhâ fhaodadh barrachd fheartan a bhith air an cur ris san Ă m ri teachd.
Is e am fuasgladh as sĂŹmplidh don duilgheadas seo colbh a chruthachadh ann an clĂ r an stòr-dĂ ta airson gach luach feart agus dĂŹreach na luachan a tha a dhĂŹth airson eisimpleir sònraichte de dhâeintiteas a lĂŹonadh. Sgoinneil! Duilgheadas air fhuasgladh... gus am bi milleanan de chlĂ ran anns aâ chlĂ r agad agus feumaidh tu clĂ r Ăšr a chur ris.
Beachdaicheamaid air pĂ tran EAV (), tha e gu math cumanta. Tha eintiteasan (clĂ ran) ann an aon chlĂ r, tha ainmean thogalaichean (feartan) ann an clĂ r eile, agus tha treas clĂ r aâ ceangal eintiteasan ris na feartan aca agus tha luachan nan feartan sin ann airson an eintiteas lĂ ithreach. Leigidh seo leat seataichean eadar-dhealaichte de fheartan a bhith agad airson diofar nithean, a bharrachd air feartan a chur ris sa bhad, gun structar an stòr-dĂ ta atharrachadh.
Ach, cha bhiodhinn aâ sgrĂŹobhadh na dreuchd seo mura biodh cuid de eas-bhuannachdan ann an dòigh-obrach EVA. Mar eisimpleir, feumaidh dĂ cheangal a bhith anns aâ cheist gus aon eintiteas no barrachd fhaighinn le aon fheart anns gach fear: aâ chiad cheangal leis aâ chlĂ r fheartan, an dĂ rna ceangal leis aâ chlĂ r luachan. Ma tha dĂ fheart aig eintiteas, tha feum air ceithir ceanglaichean! A bharrachd air an sin, mar as trice bidh na feartan uile air an stòradh mar shreangan, a tha ag adhbhrachadh èigneachadh seòrsa airson an toradh agus aâ chlĂ s WHERE. Ma sgrĂŹobhas tu tòrr cheistean, tha seo gu math sgudail a thaobh cleachdadh ghoireasan.
A dhâaindeoin nan easbhaidhean follaiseach seo, tha EAV air a bhith air a chleachdadh o chionn fhada gus na seòrsaichean dhuilgheadasan seo fhuasgladh. Bâ e easbhaidhean do-sheachanta a bhâ annta sin, agus cha robh roghainn eile nas fheĂ rr ann idir.
Ach an uairsin nochd âteicneòlasâ Ăšr ann am PostgreSQLâŚ
Aâ tòiseachadh le PostgreSQL 9.4, chaidh an seòrsa dĂ ta JSONB a chur ris airson dĂ ta dĂ -chĂ nanach JSON a stòradh. Ged a bheir stòradh JSON san fhòrmat seo beagan a bharrachd Ă ite is Ăšine na JSON teacsa lom, tha obrachaidhean leis tòrr nas luaithe. Tha JSONB cuideachd aâ toirt taic do chlĂ r-amais, aâ dèanamh cheistean eadhon nas luaithe.
Leigidh an seòrsa dĂ ta JSONB leinn am pĂ tran EAV trom a chur an Ă ite le bhith aâ cur dĂŹreach aon cholbh JSONB ris aâ chlĂ r eintiteas againn, aâ sĂŹmpleachadh dealbhadh an stòr-dĂ ta gu mòr. Ach, tha mòran ag argamaid gu bheil seo aâ tighinn aig cosgais a thaobh coileanadh⌠Sin as coireach gun do sgrĂŹobh mi an artaigil seo.
Aâ stèidheachadh stòr-dĂ ta deuchainn
Airson aâ choimeas seo, chruthaich mi an stòr-dĂ ta air stĂ ladh Ăšr de PostgreSQL 9.5 air an togail $80. Ubuntu 14.04 Ăs dèidh dhomh cuid de pharaimearan a rèiteachadh ann am postgresql.conf ruith mi sgriobt aâ cleachdadh psql. Gus an dĂ ta a thaisbeanadh mar EAV, chaidh na clĂ ran a leanas a chruthachadh:
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
);
Gu h-ĂŹosal tha clĂ r far an tèid an aon dĂ ta a stòradh, ach le feartan ann an colbh JSONB â seilbhean.
CREATE TABLE entity_jsonb (
id SERIAL PRIMARY KEY,
name TEXT,
description TEXT,
properties JSONB
);
Tha e aâ coimhead tòrr nas sĂŹmplidh, nach eil? An uairsin chaidh a chur ris na clĂ ran eintiteas (eintiteas & eintiteas_jsonb) 10 millean clĂ r, agus mar sin, bha an clĂ r air a lĂŹonadh le dĂ ta co-ionann far an deach am pĂ tran EAV agus an dòigh-obrach leis aâ cholbh JSONB a chleachdadh â feartan eintiteas_jsonbMar sin, fhuair sinn grunn sheòrsaichean dĂ ta eadar-dhealaichte thar an t-seata iomlan de thogalaichean. Eisimpleir dĂ ta:
{
id: 1
name: "Entity1"
description: "Test entity no. 1"
properties: {
color: "red"
lenght: 120
width: 3.1882420
hassomething: true
country: "Belgium"
}
}Mar sin, tha dĂ ta co-ionann againn a-nis airson an dĂ roghainn. Tòisichidh sinn aâ dèanamh coimeas eadar na buileachadh ann am fĂŹor bheatha!
Aâ sĂŹmpleachadh an dealbhaidh
Chaidh iomradh a thoirt roimhe seo gun deach dealbhadh an stòr-dĂ ta a dhèanamh gu math nas sĂŹmplidhe: aon chlĂ r, aâ cleachdadh colbh JSONB airson feartan, an Ă ite trĂŹ clĂ ran airson EAV. Ach ciamar a tha seo ag eadar-theangachadh gu ceistean? Tha Ăšrachadh feart aon eintiteas coltach ris an seo:
-- 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;
Mar a chĂŹ thu, chan eil an t-iarrtas mu dheireadh aâ coimhead nas sĂŹmplidh. Gus luach feart ann an nĂŹ JSONB Ăšrachadh, feumaidh sinn an gnĂŹomh a chleachdadh , agus feumaidh sinn an luach Ăšr againn a thoirt seachad mar nĂŹ JSONB. Ach, chan fheum sinn comharraiche sam bith a bhith againn ro-lĂ imh. Aâ coimhead air eisimpleir EAV, feumaidh fios a bhith againn air an dĂ chuid an entity_id agus an entity_attribute_id gus an Ăšrachadh a dhèanamh. Ma tha thu airson feart Ăšrachadh ann an colbh JSONB stèidhichte air ainm an nĂŹ, thèid a dhèanamh ann an aon loidhne shĂŹmplidh.
A-nis taghamaid an eintiteas a dhâ Ăšraich sinn stèidhichte air a dhath Ăšr:
-- 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';
Tha mi aâ smaoineachadh gun urrainn dhuinn aontachadh gu bheil an dĂ rna fear nas giorra (Ă s aonais an join!) agus mar sin nas so-leughaidh. Bidh JSONB aâ buannachadh an seo! Bidh sinn aâ cleachdadh an obraiche JSON ->> gus an dath fhaighinn air ais mar luach teacsa bhon nĂŹ JSONB. Tha dĂ rna dòigh ann cuideachd airson an aon toradh fhaighinn anns aâ mhodail JSONB aâ cleachdadh an obraiche @>:
-- JSONB
SELECT name
FROM entity_jsonb
WHERE properties @> '{"color": "blue"}';
Tha seo beagan nas iom-fhillte: bidh sinn aâ sgrĂšdadh a bheil an nĂŹ JSON anns aâ cholbh thogalaichean aâ gabhail a-steach an nĂŹ air taobh deas an obraiche @>. Nas lugha so-leughaidh, nas èifeachdaiche (faic gu h-ĂŹosal).
SĂŹmpleamaid cleachdadh JSONB eadhon nas fhaide nuair a dhâ fheumas tu iomadh feart a thaghadh aig an aon Ă m. Seo far a bheil dòigh-obrach JSONB aâ deĂ rrsadh: bidh sinn dĂŹreach aâ taghadh fheartan mar cholbhan a bharrachd anns an t-seata thoraidhean againn, gun fheum air joints:
-- JSONB
SELECT name
, properties ->> 'color'
, properties ->> 'country'
FROM entity_jsonb
WHERE id = 120;
Le EAV, feumaidh tu dĂ cheangal airson gach feart a tha thu airson ceist a chur air. Nam bheachd-sa, tha na ceistean gu h-Ă rd aâ sealltainn sĂŹmpleachadh mòr ann an dealbhadh stòr-dĂ ta. ChĂŹ thu cuideachd barrachd eisimpleirean air mar a sgrĂŹobhas tu ceistean JSONB ann an post.
A-nis tha an t-Ă m ann bruidhinn mu choileanadh.
Coileanadh
Gus coimeas a dhèanamh eadar an coileanadh a chleachd mi ann an ceistean gus an Ăšine cur gu bĂ s obrachadh a-mach. Chaidh gach ceist a chur gu bĂ s co-dhiĂš trĂŹ tursan, leis gu bheil am planaiche ceist aâ toirt nas fhaide aâ chiad uair. An toiseach, ruith mi na ceistean gun chlĂ r-amais sam bith. Gu follaiseach, bha seo na bhuannachd do JSONB, leis nach bâ urrainn dha na ceanglaichean a bha a dhĂŹth airson EAV clĂ ran-amais a chleachdadh (cha robh raointean iuchair chèin air an clĂ r-amais). Ăs deidh sin, chruthaich mi clĂ r-amais air an dĂ cholbh iuchair chèin de chlĂ r luach EAV, a bharrachd air clĂ r-amais airson colbh JSONB.
Sheall Úrachaidhean dà ta na toraidhean Úine a leanas (ann am ms). Thoir an aire gu bheil an sgèile logaritmach:

Tha sinn aâ faicinn gu bheil JSONB gu math (>50000x) nas luaithe na EAV Ă s aonais clĂ ran-amais, air an adhbhar a chaidh ainmeachadh gu h-Ă rd. Nuair a bhios sinn aâ clĂ radh colbhan prĂŹomh iuchair, cha mhòr nach eil an diofar aâ dol Ă bith, ach tha JSONB fhathast 1,3x nas luaithe na EAV. Thoir an aire nach eil buaidh sam bith aig aâ chlĂ r-amais air colbh JSONB an seo, leis nach eil sinn aâ cleachdadh colbh nan togalaichean anns na slatan-tomhais measaidh.
Airson taghadh dà ta stèidhichte air luach seilbh, gheibh sinn na toraidhean a leanas (sgèile à bhaisteach):

ChĂŹ thu gu bheil JSONB a-rithist nas luaithe na EAV Ă s aonais chlĂ r-amais, ach nuair a thèid EAV a chlĂ r-amais, tha e fhathast nas luaithe na JSONB. Ach an uairsin chunnaic mi gu robh na h-amannan airson ceistean JSONB mar an ceudna, agus thug sin orm a bhith aâ faicinn nach tèid clĂ ran-amais GIN a bhrosnachadh. A rèir choltais, nuair a chleachdas tu clĂ r-amais GIN air colbh le feartan lĂ n-shluaigh, chan eil e aâ toirt buaidh ach nuair a chleachdas tu an gnĂŹomhaiche in-ghabhail @>. Chleachd mi seo ann an deuchainn Ăšr, agus bha buaidh mhòr aige air an Ăšine: dĂŹreach 0,153 ms! Tha sin 15000 uair nas luaithe na EAV agus 25000 uair nas luaithe na an gnĂŹomhaiche ->>.
Tha mi aâ smaoineachadh gun robh e gu math luath!
Meud chlà ran stòr-dà ta
Dèanamaid coimeas eadar meudan nan clà ran airson an dà dhòigh-obrach. Ann am psql, is urrainn dhuinn meud nan clà ran agus nan clà ran-amais uile a thaisbeanadh leis an à ithne dti+

Leis an dòigh-obrach EAV, tha meudan nan clĂ ran timcheall air 3068 MB, agus tha na clĂ ran-amais suas ri 3427 MB, airson 6,43 GB san iomlan. Aâ cleachdadh an dòigh-obrach JSONB, bidh an clĂ r aâ cleachdadh 1817 MB agus aâ dèanamh chlĂ r-amais de 318 MB, airson 2,08 GB san iomlan. Sin an treas cuid den mheud! Chuir seo iongnadh orm beagan, leis gu bheil sinn aâ stòradh ainmean thogalaichean anns gach nĂŹ JSONB.
Ach tha na h-Ă ireamhan aâ bruidhinn air an son fhèin: ann an EAV, bidh sinn aâ stòradh dĂ iuchair cèin slĂ n-Ă ireamh gach luach feart, agus mar thoradh air sin bidh 8 bytes de dhĂ ta a bharrachd ann. A bharrachd air an sin, ann an EAV, thèid a h-uile luach feart a stòradh mar theacsa, agus cleachdaidh JSONB luachan Ă ireamhach is loidsigeach gu h-inntinneach far a bheil sin comasach, agus mar thoradh air sin bidh lorg-coise nas lugha ann.
Builean
Gu h-iomlan, tha mi aâ smaoineachadh gum faod stòradh fheartan eintiteas ann an cruth JSONB dealbhadh is cumail suas an stòr-dĂ ta agad a dhèanamh gu math nas sĂŹmplidhe. Ma nĂŹ thu tòrr cheistean, bidh e dha-rĂŹribh nas èifeachdaiche a h-uile cĂ il a stòradh san aon chlĂ r ris an eintiteas. Tha e na bhuannachd mar-thĂ gu bheil e aâ sĂŹmpleachadh eadar-obrachadh dĂ ta, ach tha an stòr-dĂ ta a thig Ă s trĂŹ tursan nas lugha ann am meud cuideachd.
Cuideachd, stèidhichte air toraidhean aâ chomharra-tomhais, is urrainn dhuinn a cho-dhĂšnadh gu bheil am peanas coileanaidh glè bheag. Ann an cuid de chĂšisean, bidh JSONB eadhon aâ coileanadh nas luaithe na EAV, ga dhèanamh eadhon nas fheĂ rr. Ach, gu cinnteach chan eil an comharra-tomhais seo aâ còmhdach a h-uile taobh (me, eintiteasan le Ă ireamh mhòr de fheartan, Ă rdachadh mòr ann an Ă ireamh nan feartan ann an dĂ ta a thâ ann mar-thĂ , msaa.), mar sin ma tha molaidhean sam bith agad airson leasachadh, na bi leisg an leigeil seachad anns na beachdan!
Source: www.habr.com
