TL; DR: JSONB ka anpil senplifye devlopman chema baz done san sakrifye pèfòmans rechèch.
Entwodiksyon
Ann bay yon egzanp klasik pwobableman youn nan ka yo itilize pi ansyen nan mond lan nan yon baz done relasyon (baz done): nou gen yon antite, epi nou bezwen sove sèten pwopriyete (atribi) nan antite sa a. Men, se pa tout ka gen menm seri pwopriyete yo, epi plis pwopriyete yo ka ajoute nan tan kap vini an.
Fason ki pi fasil pou rezoud pwoblèm sa a se kreye yon kolòn nan tab baz done a pou chak valè pwopriyete, epi tou senpleman ranpli sa yo ki nesesè pou yon egzanp espesifik antite. Gwo! Pwoblèm rezoud... jiskaske tab ou a gen plizyè milyon dosye epi ou bezwen ajoute yon nouvo dosye.
Konsidere modèl EAV (
Sepandan, mwen pa ta dwe ekri pòs sa a si pa ta gen kèk enkonvenyans nan apwòch la EVA. Se konsa, pou egzanp, pou jwenn youn oswa plizyè antite ki gen 1 atribi chak, 2 rantre yo obligatwa nan rechèch la: premye a se yon rantre ak tab la atribi, dezyèm lan se yon rantre ak tab la valè. Si yon antite gen 2 atribi, Lè sa a, 4 rantre yo nesesè! Anplis de sa, tout atribi yo anjeneral estoke kòm fisèl, ki rezilta nan depoze kalite pou tou de rezilta a ak kloz la WHERE. Si ou ekri yon anpil nan demann, Lè sa a, sa a se byen gaspiye an tèm de itilizasyon resous.
Malgre enpèfeksyon evidan sa yo, EAV te itilize depi lontan pou rezoud pwoblèm sa yo. Sa yo te enpèfeksyon inevitab, e pa te gen tou senpleman pa gen pi bon altènatif.
Men, Lè sa a, yon nouvo "teknoloji" parèt nan PostgreSQL ...
Kòmanse ak PostgreSQL 9.4, yo te ajoute kalite done JSONB nan magazen done binè JSON. Malgre ke estoke JSON nan fòma sa a anjeneral pran yon ti kras plis espas ak tan pase JSON tèks klè, fè operasyon sou li se pi vit. JSONB sipòte tou Indexing, ki fè demann menm pi vit.
Kalite done JSONB a pèmèt nou ranplase modèl EAV ankonbran an lè nou ajoute yon sèl kolòn JSONB sou tab antite nou an, sa ki senplifye konsepsyon baz done a anpil. Men, anpil diskite ke sa a ta dwe akonpaye pa yon diminisyon nan pwodiktivite ... Se poutèt sa mwen te ekri atik sa a.
Mete kanpe yon baz done tès
Pou konparezon sa a, mwen te kreye baz done a sou yon nouvo enstalasyon PostgreSQL 9.5 sou $80 bati a.
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
);
Anba a se yon tablo kote menm done yo pral estoke, men ak atribi nan yon kolòn kalite JSONB - pwopriyete.
CREATE TABLE entity_jsonb (
id SERIAL PRIMARY KEY,
name TEXT,
description TEXT,
properties JSONB
);
Li sanble anpil pi senp, pa vre? Lè sa a, li te ajoute nan tab antite yo (antite & entity_jsonb) 10 milyon dosye, ak kòmsadwa, yo te ranpli tablo a ak menm done yo lè l sèvi avèk modèl EAV la ak apwòch la ak yon kolòn JSONB - entity_jsonb.properties. Kidonk, nou te resevwa plizyè kalite done diferan nan mitan tout seri pwopriyete yo. Egzanp done:
{
id: 1
name: "Entity1"
description: "Test entity no. 1"
properties: {
color: "red"
lenght: 120
width: 3.1882420
hassomething: true
country: "Belgium"
}
}
Se konsa, kounye a nou gen menm done yo pou tou de opsyon. Ann kòmanse konpare aplikasyon nan travay!
Senplifye konsepsyon ou
Li te deja deklare ke konsepsyon baz done a te senplifye anpil: yon tab, lè l sèvi avèk yon kolòn JSONB pou pwopriyete, olye pou yo itilize twa tab pou EAV. Men, ki jan sa a reflete nan demann? Mete ajou yon pwopriyete antite sanble sa a:
-- 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;
Kòm ou ka wè, dènye demann lan pa sanble pi senp. Pou mete ajou valè yon pwopriyete nan yon objè JSONB nou dwe itilize fonksyon an
Koulye a, ann chwazi antite nou jis mete ajou dapre nouvo koulè li yo:
-- 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';
Mwen panse ke nou ka dakò ke dezyèm lan pi kout (pa gen okenn rantre!), Se poutèt sa, li pi lizib. JSONB genyen isit la! Nou itilize JSON ->> operatè a pou jwenn koulè a kòm yon valè tèks nan objè JSONB la. Genyen tou yon dezyèm fason pou reyalize menm rezilta a nan modèl JSONB lè l sèvi avèk @> operatè a:
-- JSONB
SELECT name
FROM entity_jsonb
WHERE properties @> '{"color": "blue"}';
Sa a se yon ti kras pi konplike: nou tcheke pou wè si objè JSON nan kolòn pwopriyete li yo gen yon objè ki sou bò dwat la nan @> operatè a. Mwens lizib, pi pwodiktif (gade anba a).
An nou fè sèvi ak JSONB menm pi fasil lè ou bezwen chwazi plizyè pwopriyete an menm tan. Sa a se kote apwòch JSONB reyèlman antre nan: nou tou senpleman chwazi pwopriyete kòm kolòn adisyonèl nan seri rezilta nou an san yo pa bezwen pou rantre:
-- JSONB
SELECT name
, properties ->> 'color'
, properties ->> 'country'
FROM entity_jsonb
WHERE id = 120;
Avèk EAV ou pral bezwen 2 rantre pou chak pwopriyete ou vle rechèch. Dapre mwen, demann ki anwo yo montre yon gwo senplifikasyon nan konsepsyon baz done. Gade plis egzanp sou fason pou ekri demann JSONB, tou nan
Koulye a, li lè yo pale sou pèfòmans.
Pwodiktivite
Pou konpare pèfòmans mwen te itilize
Aktyalizasyon done a te montre rezilta sa yo an tèm de tan (an ms). Remake byen ke echèl la se logaritmik:
Nou wè ke JSONB pi vit (> 50000-x) pase EAV si ou pa sèvi ak endèks, pou rezon ki endike anwo a. Lè nou endèks kolòn ak kle prensipal, diferans lan prèske disparèt, men JSONB toujou 1,3 fwa pi vit pase EAV. Remake byen ke endèks la sou kolòn JSONB la pa gen okenn efè isit la paske nou pa itilize kolòn pwopriyete a nan kritè evalyasyon yo.
Pou chwazi done ki baze sou valè pwopriyete a, nou jwenn rezilta sa yo (echèl nòmal):
Ou ka remake ke JSONB ankò travay pi vit pase EAV san endis, men lè EAV ak endis, li toujou ap travay pi vit pase JSONB. Men, Lè sa a, mwen te wè ke fwa yo pou demann JSONB yo te menm, sa a pouse m 'lefèt ke endèks GIN pa travay. Aparamman lè w sèvi ak yon endèks GIN sou yon kolòn ki gen pwopriyete peple, li sèlman pran efè lè w ap itilize operatè enkli @>. Mwen te itilize sa a nan yon nouvo tès epi li te gen yon gwo enpak sou tan an: sèlman 0,153ms! Sa a se 15000 fwa pi vit pase EAV ak 25000 fwa pi vit pase operatè a ->>.
Mwen panse ke li te rapid ase!
Gwosè tab baz done a
Ann konpare gwosè tab yo pou tou de apwòch. Nan psql nou ka montre gwosè a nan tout tab ak endèks lè l sèvi avèk lòd la dti+
Pou apwòch EAV a, gwosè tab yo alantou 3068 MB ak endèks jiska 3427 MB pou yon total de 6,43 GB. Apwòch JSONB itilize 1817 MB pou tab la ak 318 MB pou endèks yo, ki se 2,08 GB. Li sanble 3 fwa mwens! Reyalite sa a sezi m 'yon ti kras paske nou estoke non pwopriyete nan chak objè JSONB.
Men, toujou, nimewo yo pale pou tèt yo: nan EAV nou estoke 2 nonb antye relatif kle etranje pou chak valè atribi, sa ki lakòz 8 byte nan done adisyonèl. Anplis de sa, EAV estoke tout valè pwopriyete yo kòm tèks, pandan y ap JSONB pral sèvi ak valè nimerik ak booleyen anndan kote sa posib, sa ki lakòz yon anprint pi piti.
Rezilta
An jeneral, mwen panse ke ekonomize pwopriyete antite nan fòma JSONB ka fè konsepsyon ak kenbe baz done ou pi fasil. Si w ap kouri yon anpil nan demann, Lè sa a, kenbe tout bagay nan tab la menm jan ak antite a pral aktyèlman travay pi efikas. Ak lefèt ke sa a senplifye entèraksyon ki genyen ant done se deja yon plis, men baz done a ki kapab lakòz se 3 fwa pi piti nan volim.
Epitou, baze sou tès yo fè, nou ka konkli ke pèt pèfòmans yo trè ensiyifyan. Nan kèk ka, JSONB se menm pi vit pase EAV, sa ki fè li menm pi bon. Sepandan, referans sa a nan kou pa kouvri tout aspè (egzanp antite ki gen yon gwo kantite pwopriyete, yon ogmantasyon siyifikatif nan kantite pwopriyete done ki egziste deja,...), kidonk si ou gen nenpòt sijesyon sou fason pou amelyore yo. , tanpri santi yo lib yo kite nan kòmantè yo!
Sous: www.habr.com