Ke hoʻololi nei iā EAV me JSONB ma PostgreSQL

TL; DR: Hiki iā JSONB ke hoʻomaʻamaʻa nui i ka hoʻomohala ʻana i ka schema database me ka ʻole o ka kaumaha ʻana i ka hana nīnau.

Hōʻike

E hāʻawi i kahi hiʻohiʻona maʻamau o kekahi o nā hihia hoʻohana kahiko loa ma ka honua o kahi waihona pili (database): loaʻa iā mākou kahi hui, a pono mākou e mālama i kekahi mau waiwai (ʻano) o kēia hui. Akā, ʻaʻole like nā ʻano waiwai a pau, a hiki ke hoʻohui ʻia nā waiwai hou aʻe i ka wā e hiki mai ana.

ʻO ke ala maʻalahi e hoʻoponopono ai i kēia pilikia, ʻo ia ka hana ʻana i kahi kolamu i ka papa ʻikepili no kēlā me kēia waiwai waiwai, a hoʻopiha wale i nā mea e pono ai no kahi hui kikoʻī. Nui! Hoʻoholo ʻia ka pilikia... a hiki i kāu papaʻaina ke loaʻa nā miliona o nā moʻolelo a pono ʻoe e hoʻohui i kahi moʻolelo hou.

E noʻonoʻo i ke ʻano EAV (Hui-Hui-Waiwai), hiki pinepine ia. Aia kekahi papa ʻaina i nā hui (nā moʻolelo), aia kekahi papa ʻaina i nā inoa waiwai (nā ʻano), a ʻo ka papa ʻekolu e hoʻopili i nā hui me ko lākou mau ʻano a loaʻa ka waiwai o kēlā mau ʻano no ka hui o kēia manawa. Hāʻawi kēia iā ʻoe i ka hiki ke loaʻa nā ʻāpana like ʻole no nā mea like ʻole, a hoʻohui pū i nā waiwai ma ka lele me ka ʻole o ka hoʻololi ʻana i ka ʻōnaehana waihona.

Eia naʻe, ʻaʻole wau e kākau i kēia pou inā ʻaʻole he mau hemahema i ke ala EVA. No laila, no ka laʻana, no ka loaʻa ʻana o hoʻokahi a ʻoi aku paha nā mea i loaʻa i ka ʻano 1 kēlā me kēia, pono ʻia nā hui 2 i ka nīnau: ʻo ka mua he hui pū me ka papa kuhikuhi, ʻo ka lua he hui pū me ka papa waiwai. Inā loaʻa i kahi hui 2 mau ʻano, a laila pono nā hui 4! Hoʻohui ʻia, mālama mau ʻia nā ʻano a pau ma ke ʻano he mau kaula, e hopena i ke ʻano hoʻolei no ka hopena a me ka paukū WHERE. Inā ʻoe e kākau i nā nīnau he nui, a laila he mea makehewa kēia ma ke ʻano o ka hoʻohana waiwai.

ʻOiai kēia mau hemahema, ua hoʻohana lōʻihi ʻia ʻo EAV e hoʻoponopono i kēia mau pilikia. ʻO kēia nā hemahema hikiʻole ke pale aku, a ʻaʻohe mea ʻoi aku ka maikaʻi.
Akā ua puka mai kahi "ʻenehana" hou ma PostgreSQL ...

Hoʻomaka me PostgreSQL 9.4, ua hoʻohui ʻia ke ʻano ʻikepili JSONB e mālama i ka ʻikepili binary JSON. ʻOiai ʻo ka mālama ʻana iā JSON i kēia ʻano, ʻoi aku ka liʻiliʻi o ka manawa a me ka manawa ma mua o ka JSON kikokikona maʻamau, ʻoi aku ka wikiwiki o ka hana ʻana ma luna. Kākoʻo pū ʻo JSONB i ka kuhikuhi ʻana, ʻoi aku ka wikiwiki o nā nīnau.

Hiki i ke ʻano ʻikepili JSONB ke hoʻololi i ke kumu hoʻohālike EAV paʻakikī ma ka hoʻohui ʻana i hoʻokahi kolamu JSONB i kā mākou papa inoa, e hoʻomaʻamaʻa loa i ka hoʻolālā waihona. Akā, nui ka poʻe e hoʻopaʻapaʻa pono e hui pū ʻia me ka emi ʻana o ka huahana... ʻO ia ke kumu aʻu i kākau ai i kēia ʻatikala.

Hoʻonohonoho i kahi waihona hoʻāʻo

No kēia hoʻohālikelike, ua hana au i ka waihona ma kahi hoʻokomo hou o PostgreSQL 9.5 ma ka hale $80. ʻO DigitalOcean ʻO Ubuntu 14.04. Ma hope o ka hoʻonohonoho ʻana i kekahi mau ʻāpana ma postgresql.conf holo wau kēia palapala me ka psql. Ua hana ʻia nā papa ma lalo nei e hōʻike i ka ʻikepili ma ke ʻano 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
);

Aia ma lalo kahi papa kahi e mālama ʻia ai nā ʻikepili like, akā me nā ʻano i loko o kahi kolamu ʻano JSONB - nā mea waiwai.

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

ʻOi aku ka maʻalahi, ʻaʻole anei? A laila ua hoʻohui ʻia i nā papa ʻaina (ka hui & entity_jsonb) 10 miliona mau moʻolelo, a no laila, ua hoʻopiha ʻia ka papa ʻaina me ka ʻikepili like me ka hoʻohana ʻana i ke ʻano EAV a me ke ala me kahi kolamu JSONB - entity_jsonb.properties. No laila, ua loaʻa iā mākou nā ʻano ʻikepili like ʻole ma waena o ka pūʻulu o nā waiwai. ʻikepili laʻana:

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

No laila, loaʻa iā mākou ka ʻikepili like no nā koho ʻelua. E hoʻomaka kākou e hoʻohālikelike i nā hoʻokō ma ka hana!

E maʻalahi i kāu hoʻolālā

Ua ʻōlelo mua ʻia ua maʻalahi loa ka hoʻolālā ʻikepili: hoʻokahi papa, ma ka hoʻohana ʻana i kahi kolamu JSONB no nā waiwai, ma kahi o ka hoʻohana ʻana i ʻekolu papa no EAV. Akā pehea e hōʻike ʻia ai kēia i nā noi? ʻO ka hoʻonui ʻana i hoʻokahi waiwai hui e like me kēia:

-- 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;

E like me kāu e ʻike ai, ʻaʻole maʻalahi ka noi hope. No ka hoʻonui i ka waiwai o kahi waiwai i kahi mea JSONB pono mākou e hoʻohana i ka hana jsonb_set(), a pono e hāʻawi i kā mākou waiwai hou ma ke ʻano he mea JSONB. Akā naʻe, ʻaʻole pono mākou e ʻike i kahi mea hōʻike ma mua. Ke nānā nei i ka laʻana EAV, pono mākou e ʻike i ka entity_id a me ka entity_attribute_id i mea e hana ai i ka hoʻonui. Inā makemake ʻoe e hoʻohou i kahi waiwai ma kahi kolamu JSONB e pili ana i ka inoa mea, a laila ua hana ʻia ma kahi laina maʻalahi.

E koho kāua i ka hui a mākou i hōʻano hou ai ma muli o kona kala hou:

-- 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';

Manaʻo wau hiki iā mākou ke ʻae ʻoi aku ka pōkole o ka lua (ʻaʻohe hui!), a no laila hiki ke heluhelu ʻia. Ua lanakila ʻo JSONB ma ʻaneʻi! Hoʻohana mākou i ka JSON ->> mea hoʻohana e kiʻi i ke kala ma ke ʻano he waiwai kikokikona mai kahi mea JSONB. Aia kekahi ala ʻelua e hoʻokō ai i ka hopena like ma ka hoʻohālike JSONB me ka hoʻohana ʻana i ka mea hoʻohana @>:

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

ʻOi aku ka paʻakikī o kēia: nānā mākou e ʻike inā aia ka mea JSON ma kāna kolamu waiwai i kahi mea ma ka ʻākau o ka mea hoʻohana @>. ʻAʻole hiki ke heluhelu ʻia, ʻoi aku ka huahua (e ʻike i lalo).

E maʻalahi ka hoʻohana ʻana iā JSONB inā pono ʻoe e koho i nā waiwai he nui i ka manawa hoʻokahi. ʻO kēia kahi i komo maoli ai ke ala JSONB: koho wale mākou i nā waiwai e like me nā kolamu hou i kā mākou hopena hopena me ka ʻole o ka pono e hui pū ʻia:

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

Me EAV pono ʻoe i 2 hui no kēlā me kēia waiwai āu e makemake ai e nīnau. I koʻu manaʻo, hōʻike nā nīnau ma luna i kahi maʻalahi ma ka hoʻolālā waihona. E ʻike i nā hiʻohiʻona hou aʻe o ke kākau ʻana i nā nīnau JSONB, pū kekahi kēia pou.
ʻO ka manawa kēia e kamaʻilio e pili ana i ka hana.

'Ohanahana

E hoʻohālikelike i ka hana aʻu i hoʻohana ai E HOAKAKA I KA HOIKE i nā nīnau, e helu i ka manawa hoʻokō. Ua hoʻokō ʻia kēlā me kēia hulina ma kahi o ʻekolu manawa no ka mea ʻoi aku ka lōʻihi o ka mea hoʻolālā nīnau i ka manawa mua. Ua holo mua au i nā nīnau me ka ʻole o nā kuhikuhi. ʻIke loa, he mea maikaʻi kēia no JSONB, no ka mea, ʻaʻole hiki i nā hui i koi ʻia no EAV ke hoʻohana i nā kuhikuhi (ʻaʻole i kuhikuhi ʻia nā kī haole). Ma hope o kēia, ua hana au i papa kuhikuhi ma nā kolamu kī haole ʻelua o ka papa waiwai EAV, a me kahi kuhikuhi. KAHAI no kahi kolamu JSONB.

Ua hōʻike ka hōʻano hou ʻikepili i nā hopena e pili ana i ka manawa (ma ms). E hoʻomaopopo he logarithmic ka pālākiō:

Ke hoʻololi nei iā EAV me JSONB ma PostgreSQL

ʻIke mākou he ʻoi aku ka wikiwiki o JSONB (> 50000-x) ma mua o EAV inā ʻaʻole ʻoe e hoʻohana i nā kuhikuhi, no ke kumu i ʻōlelo ʻia ma luna. Ke kuhikuhi mākou i nā kolamu me nā kī mua, aneane nalo ka ʻokoʻa, akā ʻoi aku ka wikiwiki o JSONB ma mua o EAV. E hoʻomanaʻo, ʻaʻohe hopena o ka papa kuhikuhi ma ka kolamu JSONB ma ʻaneʻi no ka mea ʻaʻole mākou e hoʻohana i ka kolamu waiwai i nā pae loiloi.

No ke koho ʻana i ka ʻikepili e pili ana i ka waiwai waiwai, loaʻa iā mākou nā hopena aʻe (ka unahi maʻamau):

Ke hoʻololi nei iā EAV me JSONB ma PostgreSQL

Hiki iā ʻoe ke hoʻomaopopo i ka hana wikiwiki ʻana o JSONB ma mua o EAV me ka ʻole o nā kuhikuhi, akā inā ʻo EAV me nā kuhikuhi, ʻoi aku ka wikiwiki o ka hana ma mua o JSONB. Akā, ʻike wau ua like nā manawa no nā nīnau JSONB, ua hoʻoikaika iaʻu i ka hana ʻole o nā kuhikuhi GIN. ʻIke ʻia ke hoʻohana ʻoe i kahi index GIN ma kahi kolamu me nā waiwai nui, hoʻohana wale ia i ka wā e hoʻohana ai i ka mea hoʻokomo @>. Ua hoʻohana au i kēia ma kahi hoʻāʻo hou a he hopena nui ia i ka manawa: 0,153ms wale nō! He 15000 manawa ʻoi aku ka wikiwiki ma mua o EAV a he 25000 manawa ʻoi aku ka wikiwiki ma mua o ka mea hoʻohana ->>.

Manaʻo wau ua lawa ka wikiwiki!

Nui papa waihona

E hoʻohālikelike kākou i ka nui o ka pākaukau no nā ʻano ʻelua. Ma psql hiki iā mākou ke hōʻike i ka nui o nā papa a me nā kuhikuhi me ka hoʻohana ʻana i ke kauoha dti+

Ke hoʻololi nei iā EAV me JSONB ma PostgreSQL

No ka hoʻokokoke EAV, ʻo ka nui o ka papa ʻaina ma kahi o 3068 MB a me nā kuhikuhi a hiki i 3427 MB no ka huina o 6,43 GB. Hoʻohana ka JSONB i ka 1817 MB no ka papaʻaina a me 318 MB no nā kuhikuhi, ʻo ia ka 2,08 GB. Ua emi iho 3 manawa! ʻO kēia ʻoiaʻiʻo i kāhāhā iki iaʻu no ka mea mālama mākou i nā inoa waiwai i kēlā me kēia mea JSONB.

Akā naʻe, ʻōlelo nā helu no lākou iho: ma EAV mākou e mālama ai i 2 integer mau kī haole no kēlā me kēia waiwai waiwai, e loaʻa ana i 8 bytes o ka ʻikepili hou. Hoʻohui hou, mālama ʻo EAV i nā waiwai waiwai āpau ma ke ʻano he kikokikona, ʻoiai ʻo JSONB e hoʻohana i nā waiwai helu a me boolean i loko inā hiki, e hopena i kahi kapuaʻi liʻiliʻi.

Nā hopena

Ma ke ʻano holoʻokoʻa, manaʻo wau ʻo ka mālama ʻana i nā waiwai waiwai ma ka format JSONB hiki ke maʻalahi i ka hoʻolālā ʻana a me ka mālama ʻana i kāu waihona. Inā e holo ana ʻoe i nā nīnau he nui, a laila mālama ʻoe i nā mea āpau i ka papaʻaina hoʻokahi e ʻoi aku ka maikaʻi o ka hui. A ʻo ka ʻoiaʻiʻo o ka hoʻomaʻamaʻa ʻana i ka pilina ma waena o ka ʻikepili ua hoʻohui ʻia, akā ʻo ka ʻikepili hopena he 3 mau manawa liʻiliʻi i ka nui.

Eia kekahi, ma muli o nā hoʻokolohua i hana ʻia, hiki iā mākou ke hoʻoholo he mea nui ʻole ka nalowale o ka hana. I kekahi mau hihia, ʻoi aku ka wikiwiki o JSONB ma mua o EAV, e ʻoi aku ka maikaʻi. Eia naʻe, ʻaʻole i uhi ʻia kēia papa kuhikuhi i nā ʻano āpau (e like me nā hui me ka nui o nā waiwai, ka piʻi nui ʻana o ka nui o nā waiwai o ka ʻikepili i loaʻa, ...), no laila inā loaʻa iā ʻoe nā manaʻo e pili ana i ka hoʻomaikaʻi ʻana iā lākou. , e ʻoluʻolu e haʻalele i nā manaʻo!

Source: www.habr.com

Pākuʻi i ka manaʻo hoʻopuka