TL; DR: JSONB var ievÄrojami vienkÄrÅ”ot datu bÄzes shÄmas izstrÄdi, nezaudÄjot vaicÄjuma veiktspÄju.
Ievads
Sniegsim klasisku piemÄru vienam no senÄkajiem relÄciju datu bÄzes (datu bÄzes) lietoÅ”anas gadÄ«jumiem pasaulÄ: mums ir entÄ«tija, un mums ir jÄsaglabÄ noteikti Ŕīs entÄ«tijas rekvizÄ«ti (atribÅ«ti). TaÄu ne visiem gadÄ«jumiem var bÅ«t vienÄda rekvizÄ«tu kopa, un nÄkotnÄ var tikt pievienoti vairÄki rekvizÄ«ti.
VienkÄrÅ”Äkais veids, kÄ atrisinÄt Å”o problÄmu, ir izveidot kolonnu datu bÄzes tabulÄ katrai rekvizÄ«ta vÄrtÄ«bai un vienkÄrÅ”i aizpildÄ«t tos, kas nepiecieÅ”ami konkrÄtai entÄ«tijas instancei. Lieliski! ProblÄma atrisinÄta... lÄ«dz jÅ«su tabulÄ ir miljoniem ierakstu un jums ir jÄpievieno jauns ieraksts.
Apsveriet EAV modeli (
TomÄr es nerakstÄ«tu Å”o ziÅu, ja EVA pieejai nebÅ«tu negatÄ«vu pusi. TÄtad, piemÄram, lai iegÅ«tu vienu vai vairÄkas entÄ«tijas, kurÄm katrai ir 1 atribÅ«ts, vaicÄjumÄ ir nepiecieÅ”ami 2 savienojumi: pirmais ir savienojums ar atribÅ«tu tabulu, otrais ir savienojums ar vÄrtÄ«bu tabulu. Ja entÄ«tijai ir 2 atribÅ«ti, tad nepiecieÅ”ami 4 savienojumi! TurklÄt visi atribÅ«ti parasti tiek saglabÄti kÄ virknes, kÄ rezultÄtÄ tiek veikta tipa apraide gan rezultÄtam, gan klauzulai WHERE. Ja jÅ«s rakstÄt daudz vaicÄjumu, tas ir diezgan izŔķÄrdÄ«gs resursu izmantoÅ”anas ziÅÄ.
Neskatoties uz Å”iem acÄ«mredzamajiem trÅ«kumiem, EAV jau sen ir izmantots, lai atrisinÄtu Å”Äda veida problÄmas. Tie bija neizbÄgami trÅ«kumi, un labÄkas alternatÄ«vas vienkÄrÅ”i nebija.
Bet tad PostgreSQL parÄdÄ«jÄs jauna ātehnoloÄ£ijaā...
SÄkot ar PostgreSQL 9.4, JSONB datu tips tika pievienots JSON binÄro datu glabÄÅ”anai. Lai gan JSON glabÄÅ”ana Å”ajÄ formÄtÄ parasti aizÅem nedaudz vairÄk vietas un laika nekÄ vienkÄrÅ”a teksta JSON, darbÄ«bu veikÅ”ana ar to ir daudz ÄtrÄka. JSONB atbalsta arÄ« indeksÄÅ”anu, kas padara vaicÄjumus vÄl ÄtrÄkus.
JSONB datu tips ļauj mums aizstÄt apgrÅ«tinoÅ”o EAV modeli, pievienojot tikai vienu JSONB kolonnu mÅ«su entÄ«tiju tabulai, ievÄrojami vienkÄrÅ”ojot datu bÄzes dizainu. Bet daudzi iebilst, ka tam vajadzÄtu bÅ«t kopÄ ar produktivitÄtes samazinÄÅ”anos... TÄpÄc es arÄ« uzrakstÄ«ju Å”o rakstu.
Testu datu bÄzes iestatÄ«Å”ana
Å im salÄ«dzinÄjumam es izveidoju datu bÄzi, izmantojot jaunu PostgreSQL 9.5 instalÄciju ar 80 $ bÅ«vÄjumu
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
);
ZemÄk ir tabula, kurÄ tiks glabÄti tie paÅ”i dati, bet ar atribÅ«tiem JSONB tipa kolonnÄ - Ä«paŔības.
CREATE TABLE entity_jsonb (
id SERIAL PRIMARY KEY,
name TEXT,
description TEXT,
properties JSONB
);
IzskatÄs daudz vienkÄrÅ”Äk, vai ne? PÄc tam tas tika pievienots entÄ«tiju tabulÄm (organizÄcija & entity_jsonb) 10 miljoni ierakstu, un attiecÄ«gi tabula tika aizpildÄ«ta ar tiem paÅ”iem datiem, izmantojot EAV modeli un pieeju ar JSONB kolonnu - entity_jsonb.properties. TÄdÄjÄdi mÄs saÅÄmÄm vairÄkus dažÄdus datu tipus no visas rekvizÄ«tu kopas. Datu piemÄri:
{
id: 1
name: "Entity1"
description: "Test entity no. 1"
properties: {
color: "red"
lenght: 120
width: 3.1882420
hassomething: true
country: "Belgium"
}
}
Tagad mums ir vienÄdi dati par abÄm iespÄjÄm. SÄksim salÄ«dzinÄt implementÄcijas darbÄ!
VienkÄrÅ”ojiet savu dizainu
IepriekÅ” tika teikts, ka datu bÄzes dizains tika ievÄrojami vienkÄrÅ”ots: viena tabula, rekvizÄ«tu noteikÅ”anai izmantojot JSONB kolonnu, nevis trÄ«s tabulas EAV. Bet kÄ tas tiek atspoguļots pieprasÄ«jumos? Viena entÄ«tijas Ä«paÅ”uma atjauninÄÅ”ana izskatÄs Å”Ädi:
-- 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Ä redzat, pÄdÄjais pieprasÄ«jums neŔķiet vienkÄrÅ”Äks. Lai atjauninÄtu rekvizÄ«ta vÄrtÄ«bu JSONB objektÄ, mums ir jÄizmanto funkcija
Tagad atlasÄ«sim entÄ«tiju, kuru tikko atjauninÄjÄm, pamatojoties uz tÄs jauno krÄsu:
-- 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';
Es domÄju, ka varam piekrist, ka otrais ir Ä«sÄks (nav pievienoties!), tÄpÄc lasÄmÄks. Å eit uzvar JSONB! MÄs izmantojam operatoru JSON ->>, lai iegÅ«tu krÄsu kÄ teksta vÄrtÄ«bu no JSONB objekta. Ir arÄ« otrs veids, kÄ sasniegt tÄdu paÅ”u rezultÄtu JSONB modelÄ«, izmantojot @> operatoru:
-- JSONB
SELECT name
FROM entity_jsonb
WHERE properties @> '{"color": "blue"}';
Tas ir nedaudz sarežģītÄk: mÄs pÄrbaudÄm, vai JSON objekts tÄ rekvizÄ«tu kolonnÄ satur objektu, kas atrodas pa labi no operatora @>. MazÄk lasÄms, produktÄ«vÄks (skatÄ«t zemÄk).
PadarÄ«sim JSONB lietoÅ”anu vÄl vienkÄrÅ”Äku, ja jums bÅ«s jÄatlasa vairÄki rekvizÄ«ti vienlaikus. Å eit patieÅ”Äm parÄdÄs JSONB pieeja: mÄs vienkÄrÅ”i atlasÄm rekvizÄ«tus kÄ papildu kolonnas mÅ«su rezultÄtu kopÄ, neizmantojot savienojumus:
-- JSONB
SELECT name
, properties ->> 'color'
, properties ->> 'country'
FROM entity_jsonb
WHERE id = 120;
Izmantojot EAV, jums bÅ«s nepiecieÅ”ami 2 savienojumi katram Ä«paÅ”umam, kuru vÄlaties vaicÄt. ManuprÄt, iepriekÅ” minÄtie vaicÄjumi parÄda lielu datu bÄzes dizaina vienkÄrÅ”oÅ”anu. Skatiet citus piemÄrus, kÄ rakstÄ«t JSONB vaicÄjumus, arÄ« iekÅ”Ä
Tagad ir pienÄcis laiks runÄt par sniegumu.
ŠŃŠ¾ŠøŠ·Š²Š¾Š“ŠøŃŠµŠ»ŃŠ½Š¾ŃŃŃ
Lai salÄ«dzinÄtu veiktspÄju, es izmantoju
Datu atjauninÄjums uzrÄdÄ«ja Å”Ädus rezultÄtus laika izteiksmÄ (ms). Å emiet vÄrÄ, ka skala ir logaritmiska:
MÄs redzam, ka JSONB ir daudz (> 50000-x) ÄtrÄks par EAV, ja neizmantojat indeksus iepriekÅ” minÄtÄ iemesla dÄļ. Kad mÄs indeksÄjam kolonnas ar primÄrajÄm atslÄgÄm, atŔķirÄ«ba gandrÄ«z pazÅ«d, taÄu JSONB joprojÄm ir 1,3 reizes ÄtrÄks nekÄ EAV. Å
emiet vÄrÄ, ka indeksam kolonnÄ JSONB Å”eit nav nekÄdas ietekmes, jo mÄs neizmantojam rekvizÄ«tu kolonnu vÄrtÄÅ”anas kritÄrijos.
Lai atlasÄ«tu datus, pamatojoties uz Ä«paÅ”uma vÄrtÄ«bu, mÄs iegÅ«stam Å”Ädus rezultÄtus (parastÄ mÄrogÄ):
Varat pamanÄ«t, ka JSONB atkal darbojas ÄtrÄk nekÄ EAV bez indeksiem, bet, kad EAV ar indeksiem, tas joprojÄm darbojas ÄtrÄk nekÄ JSONB. Bet tad es redzÄju, ka JSONB vaicÄjumu laiki bija vienÄdi, un tas mani pamudinÄja uz faktu, ka GIN indeksi nedarbojas. AcÄ«mredzot, ja izmantojat GIN indeksu kolonnÄ ar aizpildÄ«tiem rekvizÄ«tiem, tas stÄjas spÄkÄ tikai tad, ja tiek izmantots operators include @>. Es to izmantoju jaunÄ testÄ, un tam bija milzÄ«ga ietekme uz laiku: tikai 0,153 ms! Tas ir 15000 25000 reižu ÄtrÄk nekÄ EAV un XNUMX XNUMX reižu ÄtrÄk nekÄ ->> operators.
Es domÄju, ka tas bija pietiekami Ätri!
Datu bÄzes tabulas lielums
SalÄ«dzinÄsim tabulu izmÄrus abÄm pieejÄm. Psql mÄs varam parÄdÄ«t visu tabulu un indeksu lielumu, izmantojot komandu dti+
EAV pieejai tabulu izmÄri ir aptuveni 3068 MB un indeksÄti lÄ«dz 3427 MB, kopÄ 6,43 GB. JSONB pieeja izmanto 1817 MB tabulai un 318 MB indeksiem, kas ir 2,08 GB. IzrÄdÄs 3 reizes mazÄk! Å is fakts mani nedaudz pÄrsteidza, jo mÄs glabÄjam Ä«paÅ”umu nosaukumus katrÄ JSONB objektÄ.
TomÄr skaitļi runÄ paÅ”i par sevi: EAV mÄs uzglabÄjam 2 veselas ÄrÄjÄs atslÄgas katrai atribÅ«ta vÄrtÄ«bai, kÄ rezultÄtÄ tiek iegÅ«ti 8 baiti papildu datu. TurklÄt EAV saglabÄ visas Ä«paÅ”uma vÄrtÄ«bas kÄ tekstu, savukÄrt JSONB, ja iespÄjams, iekÅ”Äji izmantos skaitliskÄs un BÅ«la vÄrtÄ«bas, tÄdÄjÄdi radot mazÄku nospiedumu.
RezultÄti
KopumÄ es domÄju, ka entÄ«tijas rekvizÄ«tu saglabÄÅ”ana JSONB formÄtÄ var ievÄrojami atvieglot datu bÄzes projektÄÅ”anu un uzturÄÅ”anu. Ja izpildÄt daudz vaicÄjumu, tad, turot visu vienÄ tabulÄ ar entÄ«tiju, tas faktiski darbosies efektÄ«vÄk. Un tas, ka tas vienkÄrÅ”o datu mijiedarbÄ«bu, jau ir pluss, bet iegÅ«tÄ datubÄze ir 3 reizes mazÄka apjoma ziÅÄ.
TÄpat, pamatojoties uz veiktajÄm pÄrbaudÄm, varam secinÄt, ka veiktspÄjas zudumi ir ļoti niecÄ«gi. Dažos gadÄ«jumos JSONB ir pat ÄtrÄks par EAV, padarot to vÄl labÄku. TomÄr Å”is etalons, protams, neaptver visus aspektus (piemÄram, entÄ«tijas ar ļoti lielu rekvizÄ«tu skaitu, ievÄrojams esoÅ”o datu rekvizÄ«tu skaita pieaugums...), tÄdÄļ, ja jums ir kÄdi ieteikumi, kÄ tos uzlabot , lÅ«dzu, nekautrÄjieties atstÄt komentÄros!
Avots: www.habr.com