Ho fetola EAV ka JSONB ho PostgreSQL

TL; DR: JSONB e ka nolofatsa haholo nts'etsopele ea schema ea database ntle le ho tela ts'ebetso ea lipotso.

Selelekela

Ha re fane ka mohlala oa khale oa mohlomong e 'ngoe ea linyeoe tsa khale ka ho fetisisa lefatšeng tsa polokelo ea litaba (database): re na le setheo, 'me re hloka ho boloka thepa e itseng (litšoaneleho) tsa setheo sena. Empa ha se maemo ohle a ka bang le sete e tšoanang ea thepa, mme thepa e eketsehileng e ka eketsoa nakong e tlang.

Tsela e bonolo ka ho fetisisa ea ho rarolla bothata bona ke ho theha kholumo tafoleng ea database bakeng sa boleng bo bong le bo bong ba thepa, 'me u tlatse feela tse hlokahalang bakeng sa mohlala o itseng oa mokhatlo. E kholo! Bothata bo rarollotsoe... ho fihlela tafole ea hau e na le lirekoto tse limilione mme o hloka ho kenya rekoto e ncha.

Nahana ka mohlala oa EAV (Boleng ba Sebopeho-Sebopeho), e etsahala hangata. Tafole e 'ngoe e na le mekhatlo (lirekoto), tafole e' ngoe e na le mabitso a thepa (litšoaneleho), 'me tafole ea boraro e amahanya mekhatlo le litšobotsi tsa eona mme e na le boleng ba litšoaneleho tseo bakeng sa setheo sa hajoale. Sena se u fa bokhoni ba ho ba le lihlopha tse fapaneng tsa thepa bakeng sa lintho tse fapaneng, hape u kenye thepa ka fofa ntle le ho fetola sebopeho sa polokelo ea litaba.

Leha ho le joalo, nka be ke sa ngola poso ena haeba ho ne ho se na mefokolo ea mokhoa oa EVA. Kahoo, ho etsa mohlala, ho fumana setheo se le seng kapa ho feta se nang le tšobotsi e le 'ngoe, ho hlokahala lihokela tse 1 potsong: ea pele ke ho kopanya le tafole ea semelo, ea bobeli ke ho kopanya le tafole ea boleng. Haeba setheo se na le litšoaneleho tse 2, ho tla hlokahala likopano tse 2! Ho feta moo, litšoaneleho tsohle li bolokoa joalo ka likhoele, e leng se etsang hore ho be le mofuta oa sephetho le poleloana ea WHERE. Haeba u ngola lipotso tse ngata, joale sena se senya haholo mabapi le tšebeliso ea lisebelisoa.

Ho sa tsotellehe mefokolo ena e totobetseng, EAV haesale e sebelisoa ho rarolla mefuta ena ea mathata. Tsena e ne e le mefokolo e ke keng ea qojoa, ’me ho hang ho ne ho se mokhoa o mong o molemo ho feta oo.
Empa joale ho ile ha hlaha "theknoloji" e ncha ho PostgreSQL ...

Ho qala ka PostgreSQL 9.4, mofuta oa data oa JSONB o kentsoe ho boloka data ea binary ea JSON. Leha ho boloka JSON ka sebopeho sena hangata ho nka sebaka le nako e nyane ho feta mongolo o hlakileng JSON, ho etsa ts'ebetso ho eona ho potlakile haholo. JSONB e boetse e ts'ehetsa indexing, e etsang hore lipotso li be kapele le ho feta.

Mofuta oa data oa JSONB o re lumella ho nka sebaka sa mokhoa o boima oa EAV ka ho kenyelletsa kholumo e le 'ngoe feela ea JSONB tafoleng ea rona ea mokhatlo, e nolofatsa haholo moralo oa database. Empa ba bangata ba pheha khang ea hore sena se lokela ho tsamaea le ho fokotseha ha tlhahiso ... Ke kahoo ke ngotseng sehlooho sena.

Ho theha database ea liteko

Bakeng sa papiso ena, ke thehile database mabapi le kopo e ncha ea PostgreSQL 9.5 mohahong oa $80. DigitalOcean Ubuntu 14.04. Ka mor'a ho beha mekhahlelo e meng ho postgresql.conf ke ile ka matha sena script ho sebelisa psql. Litafole tse latelang li entsoe ho hlahisa lintlha ka mokhoa oa 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
);

Ka tlase ke tafole moo data e tšoanang e tla bolokoa, empa e na le litšoaneleho tsa mofuta oa JSONB kholomo - thepa.

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

E shebahala e le bonolo haholoanyane, na ha ho joalo? Ebe e eketsoa ho litafole tsa mokhatlo (mokhatlo oa & mokhatlo_jsonb) Litlaleho tse limilione tse 10, 'me ka hona, tafole e ne e tletse lintlha tse tšoanang ho sebelisa mokhoa oa EAV le mokhoa o nang le kholomo ea JSONB - entity_jsonb.properties. Kahoo, re fumane mefuta e mengata e fapaneng ea data har'a sehlopha sohle sa thepa. Lintlha tsa mohlala:

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

Kahoo joale re na le data e tšoanang bakeng sa likhetho ka bobeli. Ha re qale ho bapisa ts'ebetsong mosebetsing!

Nolofatsa moralo oa hau

Ho ile ha boleloa pejana hore moralo oa database o nolofalitsoe haholo: tafole e le 'ngoe, ka ho sebelisa kholomo ea JSONB bakeng sa thepa, ho e-na le ho sebelisa litafole tse tharo bakeng sa EAV. Empa see se bonahala joang likōpong? Ho nchafatsa thepa e le 'ngoe ho shebahala tjena:

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

Joalokaha u ka bona, kopo ea ho qetela ha e shebahale e le bonolo. Ho ntlafatsa boleng ba thepa ho ntho ea JSONB re tlameha ho sebelisa ts'ebetso jsonb_set(), mme e lokela ho fetisa boleng ba rona bo bocha joalo ka ntho ea JSONB. Leha ho le joalo, ha ho hlokahale hore re tsebe sekhetho esale pele. Ha re sheba mohlala oa EAV, re hloka ho tseba entity_id le entity_attribute_id hore re ntlafatse. Haeba u batla ho nchafatsa thepa ka har'a kholomo ea JSONB e ipapisitseng le lebitso la ntho, tsohle li entsoe ka mola o le mong o bonolo.

Joale ha re khetheng setheo seo re sa tsoa se ntlafatsa ho latela 'mala oa sona o mocha:

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

Ke nahana hore re ka lumellana hore ea bobeli e khutšoanyane (ha e kopane!), 'me ka hona e baloa haholoanyane. JSONB e hlola mona! Re sebelisa JSON ->> opareitara ho fumana 'mala joalo ka boleng ba mongolo ho tsoa ho ntho ea JSONB. Ho boetse ho na le mokhoa oa bobeli oa ho fihlela sephetho se ts'oanang mofuteng oa JSONB o sebelisa @> opareitara:

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

Sena se rarahane haholoanyane: re hlahloba ho bona hore na ntho ea JSON e kholomong ea thepa ea eona e na le ntho e ka letsohong le letona la @> opareitara. Ha e balehe, e hlahisa litholoana haholo (sheba ka tlase).

Ha re e sebelisetseng JSONB le ho feta ha o hloka ho khetha thepa e mengata ka nako e le 'ngoe. Mona ke moo mokhoa oa JSONB o hlileng o kenang teng: re khetha thepa feela joalo ka likholomo tse ling ho sephetho sa rona ntle le tlhoko ea ho kopanya:

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

Ka EAV o tla hloka lihokelo tse 2 bakeng sa thepa ka 'ngoe eo u batlang ho e botsa. Ka maikutlo a ka, lipotso tse ka holimo li bontša ho nolofatsa ho hoholo ha moralo oa database. Sheba mehlala e meng ea ho ngola lipotso tsa JSONB, hape ho sena poso.
Joale ke nako ea ho bua ka ts'ebetso.

Tlhahiso

Ho bapisa ts'ebetso eo ke e sebelisitseng HLALOSA HLALELE ka lipotso, ho bala nako ea ho phethahatsa. Potso e 'ngoe le e 'ngoe e entsoe bonyane makhetlo a mararo hobane moralo oa potso o nka nako e telele khetlo la pele. Pele ke ile ka botsa lipotso ntle le li-index. Ho hlakile hore ona e ne e le molemo oa JSONB, kaha lihokelo tse hlokahalang bakeng sa EAV li ne li sa khone ho sebelisa li-index (libaka tsa bohlokoa tsa kantle ho naha li ne li sa thathamisoa). Ka mor'a sena ke ile ka theha index holim'a litšiea tse 2 tse tsoang linaheng tse ling tsa tafole ea boleng ba EAV, hammoho le index GIN bakeng sa kholomo ea JSONB.

Ntlafatso ea data e bonts'itse liphetho tse latelang ho latela nako (ho ms). Hlokomela hore sekala ke logarithmic:

Ho fetola EAV ka JSONB ho PostgreSQL

Rea bona hore JSONB e potlakile haholo (> 50000-x) ho feta EAV haeba u sa sebelise li-index, ka lebaka le boletsoeng ka holimo. Ha re supa litšiea tse nang le linotlolo tsa mantlha, phapang e batla e nyamela, empa JSONB e ntse e le makhetlo a 1,3 ka potlako ho feta EAV. Hlokomela hore index e kholomong ea JSONB ha e na phello mona kaha ha re sebelise kholomo ea thepa maemong a tlhahlobo.

Bakeng sa ho khetha data ho latela boleng ba thepa, re fumana liphetho tse latelang (sekala se tloaelehileng):

Ho fetola EAV ka JSONB ho PostgreSQL

U ka hlokomela hore JSONB e boetse e sebetsa ka potlako ho feta EAV ntle le li-index, empa ha EAV e na le li-index, e ntse e sebetsa ka potlako ho feta JSONB. Empa joale ke ile ka bona hore linako tsa lipotso tsa JSONB lia tšoana, sena se ile sa ntšusumelletsa taba ea hore li-index tsa GIN ha li sebetse. Kamoo ho bonahalang kateng ha o sebelisa index ea GIN kholomong e nang le thepa e nang le batho ba bangata, e sebetsa feela ha o sebelisa opareitara e kenyeletsang @>. Ke sebelisitse sena tekong e ncha mme e bile le tšusumetso e kholo ka nako: ke 0,153ms feela! Ena ke makhetlo a 15000 ka potlako ho feta EAV le makhetlo a 25000 ka potlako ho feta ->> opereishene.

Ke nahana hore e ne e potlakile ho lekana!

Boholo ba tafole ea database

Ha re bapise boholo ba tafole bakeng sa mekhoa e 'meli. Ho psql re ka bonts'a boholo ba litafole le li-index tsohle re sebelisa taelo dti+

Ho fetola EAV ka JSONB ho PostgreSQL

Bakeng sa mokhoa oa EAV, boholo ba litafole bo pota-potile 3068 MB le li-index ho fihla ho 3427 MB bakeng sa kakaretso ea 6,43 GB. Mokhoa oa JSONB o sebelisa 1817 MB bakeng sa tafole le 318 MB bakeng sa li-index, e leng 2,08 GB. E hlaha ka makhetlo a 3 ka tlase! Taba ena e ile ea 'makatsa hanyenyane hobane re boloka mabitso a thepa nthong e' ngoe le e 'ngoe ea JSONB.

Empa leha ho le joalo, lipalo lia ipuella: ho EAV re boloka linotlolo tse 2 tsa kantle ho naha ka boleng ba boleng, ho fella ka li-byte tse 8 tsa data e eketsehileng. Ho feta moo, EAV e boloka boleng ba thepa eohle e le mongolo, athe JSONB e tla sebelisa linomoro le boleng ba boolean kahare moo ho khonehang, e leng se tla fella ka sebaka se senyenyane sa maoto.

Liphello

Ka kakaretso, ke nahana hore ho boloka thepa ea mokhatlo ka sebopeho sa JSONB ho ka etsa hore ho be bonolo ho rala le ho boloka database ea hau. Haeba u botsa lipotso tse ngata, joale ho boloka ntho e 'ngoe le e' ngoe e le tafoleng e le 'ngoe kaha mokhatlo o tla sebetsa ka mokhoa o atlehileng haholoanyane. 'Me taba ea hore sena se nolofatsa tšebelisano pakeng tsa data e se e ntse e le phaello, empa database e hlahisoang e na le makhetlo a 3 a nyenyane ka molumo.

Hape, ho latela liteko tse entsoeng, re ka fihlela qeto ea hore tahlehelo ea ts'ebetso ha e na thuso haholo. Maemong a mang, JSONB e potlakile ho feta EAV, e etsa hore e be betere le ho feta. Leha ho le joalo, benchmark ena ha e akarelletse likarolo tsohle (mohlala, mekhatlo e nang le thepa e ngata haholo, keketseho e kholo ea palo ea thepa ea data e teng, ...), kahoo haeba u na le litlhahiso tsa hore na u ka li ntlafatsa joang. , ka kōpo ikutloe u lokolohile ho tlohela litlhaloso!

Source: www.habr.com

Eketsa ka tlhaloso