{"id":52584,"date":"2019-11-12T00:00:00","date_gmt":"2019-11-11T21:00:00","guid":{"rendered":"https:\/\/prohoster.info\/blog\/blog_prohoster\/zamena-eav-na-jsonb-v-postgresql"},"modified":"2020-02-18T14:00:21","modified_gmt":"2020-02-18T11:00:21","slug":"zamena-eav-na-jsonb-v-postgresql","status":"publish","type":"post","link":"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/zamena-eav-na-jsonb-v-postgresql","title":{"rendered":"Byte av EAV till JSONB i PostgreSQL","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<blockquote><p>TL; DR: JSONB kan avsev\u00e4rt f\u00f6renkla utvecklingen av databasstrukturer utan att kompromissa med prestanda i fr\u00e5gorna.<\/p><\/blockquote>\n<p><\/p>\n<h3>Introduktion<\/h3>\n<p>\nL\u00e5t oss ge ett klassiskt exempel, troligen en av de \u00e4ldsta anv\u00e4ndningarna i v\u00e4rlden av relationsdatabaser (databaser): vi har en entitet och beh\u00f6ver spara specifika egenskaper (attribut) f\u00f6r denna entitet. Men inte alla instanser kan ha samma upps\u00e4ttning egenskaper, och dessutom kan det i framtiden finnas behov av att l\u00e4gga till fler egenskaper.<\/p>\n<p>Det enklaste s\u00e4ttet att l\u00f6sa detta problem \u00e4r att skapa en kolumn i databastabellen f\u00f6r varje v\u00e4rde av egenskapen och helt enkelt fylla i de som beh\u00f6vs f\u00f6r den specifika instansen av entiteten. Utm\u00e4rkt! Problemet l\u00f6st... tills dess att din tabell inneh\u00e5ller miljontals poster och du pl\u00f6tsligt beh\u00f6ver l\u00e4gga till en ny post.<\/p>\n<p>L\u00e5t oss \u00f6verv\u00e4ga EAV-m\u00f6nstret (<noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Entity%E2%80%93attribute%E2%80%93value_model\">Entity-Attribute-Value<\/a><\/noindex>), som f\u00f6rekommer ganska ofta. En tabell inneh\u00e5ller entiteter (poster), en annan tabell inneh\u00e5ller namnen p\u00e5 egenskaper (attribut), och en tredje tabell kopplar entiteter till deras attribut och inneh\u00e5ller v\u00e4rdet av dessa attribut f\u00f6r den aktuella entiteten. Detta ger dig m\u00f6jlighet att ha olika upps\u00e4ttningar egenskaper f\u00f6r olika objekt, samt att l\u00e4gga till egenskaper \"on the fly\" utan att f\u00f6r\u00e4ndra databasstrukturen.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><br \/>\n\u00c4nd\u00e5 skulle jag inte ha skrivit den h\u00e4r anteckningen om det inte fanns brister i EVA-metoden. Till exempel, f\u00f6r att h\u00e4mta en eller flera entiteter som har 1 attribut kr\u00e4vs det 2 join&#8217;er (f\u00f6reningar) i fr\u00e5gan: den f\u00f6rsta \u00e4r en f\u00f6rening med attributtabellen, den andra \u00e4r en f\u00f6rening med v\u00e4rdestabellen. Om entiteten har 2 attribut s\u00e5 beh\u00f6vs det redan 4 join&#8217;er! Dessutom lagras alla attribut vanligtvis som str\u00e4ngar, vilket leder till typomvandlingar b\u00e5de f\u00f6r resultatet och f\u00f6r WHERE-villkoret. Om du skriver m\u00e5nga fr\u00e5gor \u00e4r det ganska sl\u00f6saktigt sett ur resursanv\u00e4ndning.<\/p>\n<p>Trots dessa uppenbara nackdelar, har EAV l\u00e4nge anv\u00e4nts f\u00f6r att l\u00f6sa den h\u00e4r typen av problem. Det har varit oundvikliga nackdelar, och det har helt enkelt inte funnits n\u00e5gon b\u00e4ttre alternativ. <br \/>\nMen sedan d\u00f6k en ny \"teknologi\" upp i PostgreSQL...<\/p>\n<p>Sedan PostgreSQL 9.4 lades datatypen JSONB till f\u00f6r att lagra bin\u00e4ra JSON-data. \u00c4ven om lagring av JSON i detta format vanligtvis tar lite mer utrymme och tid j\u00e4mf\u00f6rt med enkel textbaserad JSON, g\u00e5r operationer med det mycket snabbare. JSONB st\u00f6der ocks\u00e5 indexering, vilket g\u00f6r f\u00f6rfr\u00e5gningar \u00e4nnu snabbare.<\/p>\n<p>Datatypen JSONB m\u00f6jligg\u00f6r att vi kan ers\u00e4tta det omfattande EAV-m\u00f6nstret genom att l\u00e4gga till endast en JSONB-kolumn i v\u00e5r entitetstabell, vilket f\u00f6renklar databasdesignen avsev\u00e4rt. Men m\u00e5nga h\u00e4vdar att detta b\u00f6r \u00e5tf\u00f6ljas av prestandanedg\u00e5ng... Det \u00e4r just h\u00e4r denna artikel kommer in.<\/p>\n<h3>Inst\u00e4llning av testdatabas<\/h3>\n<p>\nF\u00f6r denna j\u00e4mf\u00f6relse skapade jag en databas p\u00e5 en ny installation av PostgreSQL 9.5 p\u00e5 en 80-dollarsupps\u00e4ttning <noindex><a rel=\"nofollow\" href=\"https:\/\/www.digitalocean.com\/\">DigitalOcean<\/a><\/noindex> Ubuntu 14.04. Efter att ha justerat vissa parametrar i postgresql.conf k\u00f6rde jag <noindex><a rel=\"nofollow\" href=\"https:\/\/gist.github.com\/coussej\/80c385332ce37df6687f\">det h\u00e4r<\/a><\/noindex> ett skript med hj\u00e4lp av psql. F\u00f6r att representera data i EAV-format skapades f\u00f6ljande tabeller:<\/p>\n<pre><code class=\"pgsql\">CREATE TABLE entity ( \n  id           SERIAL PRIMARY KEY, \n  name         TEXT, \n  description  TEXT\n);\nCREATE TABLE entity_attribute (\n  id          SERIAL PRIMARY KEY, \n  name        TEXT\n);\nCREATE TABLE entity_attribute_value (\n  id                  SERIAL PRIMARY KEY, \n  entity_id           INT    REFERENCES entity(id), \n  entity_attribute_id INT    REFERENCES entity_attribute(id), \n  value               TEXT\n);\n<\/code><\/pre>\n<p>\nNedan finns en tabell d\u00e4r samma data kommer att lagras, men med attribut i en JSONB-kolumn \u2013 <i>properties<\/i>.<\/p>\n<pre><code class=\"pgsql\">CREATE TABLE entity_jsonb (\n  id          SERIAL PRIMARY KEY, \n  name        TEXT, \n  description TEXT,\n  properties  JSONB\n);\n<\/code><\/pre>\n<p>\nSer mycket enklare ut, eller hur? Sedan lades 10 miljoner poster till i entitetstabellerna (<i>entity<\/i> &amp; <i>entity_jsonb<\/i>) och motsvarande fyllts med samma data i tabellerna d\u00e4r EAV-m\u00f6nstret anv\u00e4nds och tillv\u00e4gag\u00e5ngss\u00e4ttet med JSONB-kolumnen \u2013 <i>entity_jsonb.properties<\/i>. S\u00e5ledes fick vi flera olika datatyper bland hela upps\u00e4ttningen av egenskaper. Exempeldata:<\/p>\n<pre><code class=\"json\">{\n  id:          1\n  name:        \"Entity1\"\n  description: \"Test entity no. 1\"\n  properties:  {\n    color:        \"red\"\n    length:       120\n    width:        3.1882420\n    hassomething: true\n    country:      \"Belgium\"\n  } \n}<\/code><\/pre>\n<p>\nS\u00e5, nu har vi samma data f\u00f6r tv\u00e5 alternativ. L\u00e5t oss b\u00f6rja j\u00e4mf\u00f6ra implementationerna i arbete!<\/p>\n<h3>F\u00f6renkling av design<\/h3>\n<p>\nDet har redan n\u00e4mnts att databasdesignen har f\u00f6renklats avsev\u00e4rt: en tabell, tack vare anv\u00e4ndningen av en JSONB-kolumn f\u00f6r egenskaper, ist\u00e4llet f\u00f6r att anv\u00e4nda tre tabeller f\u00f6r EAV. Men hur p\u00e5verkar detta f\u00f6rfr\u00e5gningarna? Uppdatering av en egenskap f\u00f6r en entitet ser ut som f\u00f6ljer:<\/p>\n<pre><code class=\"pgsql\">-- EAV\nUPDATE entity_attribute_value \nSET value = 'bl\u00e5' \nWHERE entity_attribute_id = 1 \n  AND entity_id = 120;\n\n-- JSONB\nUPDATE entity_jsonb \nSET properties = jsonb_set(properties, '{\"color\"}', '\"bl\u00e5\"') \nWHERE id = 120;\n<\/code><\/pre>\n<p>\nSom vi ser, ser inte den sista fr\u00e5gan enklare ut. F\u00f6r att uppdatera egenskapsv\u00e4rdet i JSONB-objektet m\u00e5ste vi anv\u00e4nda funktionen <noindex><a rel=\"nofollow\" href=\"http:\/\/www.postgresql.org\/docs\/9.5\/static\/functions-json.html\">jsonb_set()<\/a><\/noindex>, och vi m\u00e5ste skicka v\u00e5rt nya v\u00e4rde som ett JSONB-objekt. \u00c5 andra sidan beh\u00f6ver vi inte veta n\u00e5got identifierare i f\u00f6rv\u00e4g. Tittar vi p\u00e5 exemplet med EAV beh\u00f6ver vi b\u00e5de entity_id och entity_attribute_id f\u00f6r att utf\u00f6ra uppdateringen. Om du vill uppdatera en egenskap i JSONB-kolumnen baserat p\u00e5 objektets namn, s\u00e5 g\u00f6rs detta med en enkel rad.<\/p>\n<p>L\u00e5t oss nu v\u00e4lja den entitet vi just uppdaterade baserat p\u00e5 dess nya f\u00e4rg:<\/p>\n<pre><code class=\"pgsql\">-- EAV\nSELECT e.name \nFROM entity e \n  INNER JOIN entity_attribute_value eav ON e.id = eav.entity_id\n  INNER JOIN entity_attribute ea ON eav.entity_attribute_id = ea.id\nWHERE ea.name = 'color' AND eav.value = 'bl\u00e5';\n\n-- JSONB\nSELECT name \nFROM entity_jsonb \nWHERE properties -&gt;&gt; 'color' = 'bl\u00e5';\n<\/code><\/pre>\n<p>\nJag tror vi kan enas om att det andra \u00e4r kortare (utan join!), och d\u00e4rmed mer l\u00e4sbart. H\u00e4r vinner JSONB! Vi anv\u00e4nder JSON-operat\u00f6ren -&gt;&gt; f\u00f6r att f\u00e5 f\u00e4rgen som ett textv\u00e4rde fr\u00e5n JSONB-objektet. Det finns ocks\u00e5 ett andra s\u00e4tt att uppn\u00e5 samma resultat i JSONB-modellen med operat\u00f6ren @&gt; :<\/p>\n<pre><code class=\"pgsql\">-- JSONB \nSELECT name \nFROM entity_jsonb \nWHERE properties @&gt; '{\"color\": \"bl\u00e5\"}';\n<\/code><\/pre>\n<p>\nDetta \u00e4r lite mer komplicerat: vi kontrollerar om JSON-objektet i kolumnens egenskaper inneh\u00e5ller objektet som finns till h\u00f6ger om operat\u00f6ren @&gt;. Mindre l\u00e4sbart, mer effektivt (se nedan). <\/p>\n<p>L\u00e5t oss f\u00f6renkla anv\u00e4ndningen av JSONB \u00e4nnu mer n\u00e4r du beh\u00f6ver v\u00e4lja flera egenskaper samtidigt. H\u00e4r passar verkligen JSONB-ansatsen: vi v\u00e4ljer helt enkelt egenskaper som extra kolumner i v\u00e5r resultatupps\u00e4ttning utan behov av joins:<\/p>\n<pre><code class=\"pgsql\">-- JSONB \nSELECT name\n  , properties -&gt;&gt; 'color'\n  , properties -&gt;&gt; 'country'\nFROM entity_jsonb \nWHERE id = 120;\n<\/code><\/pre>\n<p>\nMed EAV beh\u00f6ver du 2 joins f\u00f6r varje egenskap som du vill fr\u00e5ga. Enligt min mening visar ovanst\u00e5ende fr\u00e5gor en stor f\u00f6renkling i databasdesignen. Du kan \u00e4ven se fler exempel p\u00e5 hur man skriver fr\u00e5gor mot JSONB i <noindex><a rel=\"nofollow\" href=\"http:\/\/schinckel.net\/2014\/05\/25\/querying-json-in-postgres\/\">detta<\/a><\/noindex> inl\u00e4gget.<br \/>\nNu \u00e4r det dags att prata om prestanda.<\/p>\n<h3>Performance<\/h3>\n<p>\nF\u00f6r att j\u00e4mf\u00f6ra prestanda anv\u00e4nde jag <noindex><a rel=\"nofollow\" href=\"http:\/\/www.postgresql.org\/docs\/9.1\/static\/sql-explain.html\">EXPLAIN ANALYZE<\/a><\/noindex> i f\u00f6rfr\u00e5gningar, f\u00f6r att ber\u00e4kna exekveringstiden. Varje f\u00f6rfr\u00e5gan k\u00f6rdes minst tre g\u00e5nger, eftersom planeringsverktyget kr\u00e4ver mer tid f\u00f6rsta g\u00e5ngen. F\u00f6rst utf\u00f6rde jag f\u00f6rfr\u00e5gningarna utan n\u00e5gra index. Uppenbarligen gav detta JSONB en f\u00f6rdel, eftersom joins som beh\u00f6vs f\u00f6r EAV inte kunde anv\u00e4nda index (f\u00e4lten med fr\u00e4mmande nycklar var inte indexerade). Efter detta skapade jag ett index f\u00f6r tv\u00e5 kolumner av fr\u00e4mmande nycklar i EAV-v\u00e4rdestabellen, samt ett index <noindex><a rel=\"nofollow\" href=\"http:\/\/www.postgresql.org\/docs\/9.1\/static\/textsearch-indexes.html\">GIN<\/a><\/noindex> f\u00f6r JSONB-kolumnen.<\/p>\n<p>Uppdateringar av data visade f\u00f6ljande resultat f\u00f6r tiden (i ms). Observera att skalan \u00e4r logaritmisk:<\/p>\n<p><img decoding=\"async\" alt=\"Byte av EAV till JSONB i PostgreSQL\" src=\"\/wp-content\/uploads\/2019\/11\/8a12ccd7a46d04868b1cc5fcaf01a581.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nVi ser att JSONB \u00e4r mycket (&gt; 50000 g\u00e5nger) snabbare \u00e4n EAV n\u00e4r index inte anv\u00e4nds, av anledningen som n\u00e4mndes ovan. N\u00e4r vi indexerar kolumner med prim\u00e4ra nycklar f\u00f6rsvinner n\u00e4stan skillnaden, men JSONB \u00e4r fortfarande 1,3 g\u00e5nger snabbare \u00e4n EAV. Observera att indexet f\u00f6r JSONB-kolumnen h\u00e4r inte har n\u00e5gon p\u00e5verkan, eftersom vi inte anv\u00e4nder egenskapskolumnen i utv\u00e4rderingskriterierna. <\/p>\n<p>F\u00f6r att h\u00e4mta data baserat p\u00e5 ett egenskapsv\u00e4rde f\u00e5r vi f\u00f6ljande resultat (normal skala):<\/p>\n<p><img decoding=\"async\" alt=\"Byte av EAV till JSONB i PostgreSQL\" src=\"\/wp-content\/uploads\/2019\/11\/e9a1fd797ef60132e661da686f6214a3.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDet \u00e4r tydligt att JSONB \u00e5terigen fungerar snabbare \u00e4n EAV utan index, men n\u00e4r EAV har index \u00e4r den fortfarande snabbare \u00e4n JSONB. Men sedan s\u00e5g jag att tiden f\u00f6r JSONB-f\u00f6rfr\u00e5gningarna var densamma, vilket ledde mig till insikten att GIN-indexet inte aktiveras. Uppenbarligen, n\u00e4r du anv\u00e4nder GIN-index f\u00f6r en kolumn med fyllda egenskaper, fungerar det bara vid anv\u00e4ndning av inklusionsoperatorn @&gt;. Jag anv\u00e4nde detta i ett nytt test, vilket hade en enorm p\u00e5verkan p\u00e5 tiden: endast 0,153 ms! Det \u00e4r 15000 g\u00e5nger snabbare \u00e4n EAV och 25000 g\u00e5nger snabbare \u00e4n operatorn -&gt;&gt;. <\/p>\n<p>Jag tycker att det var tillr\u00e4ckligt snabbt!<\/p>\n<h3>Storleken p\u00e5 databastabeller<\/h3>\n<p>\nL\u00e5t oss j\u00e4mf\u00f6ra storlekarna p\u00e5 tabellerna med b\u00e5da metoderna. I psql kan vi visa storleken f\u00f6r alla tabeller och index genom att anv\u00e4nda kommandot <b>dti+<\/b><\/p>\n<p><img decoding=\"async\" alt=\"Byte av EAV till JSONB i PostgreSQL\" src=\"\/wp-content\/uploads\/2019\/11\/c6c1fe7901fe9ae2bd446cf4ae99b923.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nF\u00f6r EAV-metoden \u00e4r storleken p\u00e5 tabellerna cirka 3068 MB och indexen upp till 3427 MB, vilket ger totalt 6,43 GB. Vid anv\u00e4ndning av JSONB-metoden anv\u00e4nds 1817 MB f\u00f6r tabellen och 318 MB f\u00f6r indexen, vilket inneb\u00e4r 2,08 GB. Det blir tre g\u00e5nger mindre! Denna siffra \u00f6verraskade mig n\u00e5got, eftersom vi lagrar namnen p\u00e5 egenskaperna i varje JSONB-objekt. <\/p>\n<p>Men siffrorna talar f\u00f6r sig sj\u00e4lva: i EAV lagrar vi 2 heltal externa nycklar f\u00f6r attributets v\u00e4rde, vilket resulterar i 8 byte ytterligare data. Dessutom lagras alla egenskapsv\u00e4rden i EAV i text, medan JSONB kommer att anv\u00e4nda numeriska och logiska v\u00e4rden inom de omr\u00e5den d\u00e4r det \u00e4r m\u00f6jligt, vilket ger en mindre datastorlek.<\/p>\n<h3>Sammanfattning<\/h3>\n<p>\nGenerellt sett anser jag att lagringen av entitets egenskaper i JSONB-formatet kan f\u00f6renkla design och underh\u00e5ll av din databas avsev\u00e4rt. Om du utf\u00f6r m\u00e5nga fr\u00e5gor, kommer allt som lagras i en tabell med entiteten verkligen att fungera mer effektivt. Och det faktum att det underl\u00e4ttar interaktionen mellan data \u00e4r redan en f\u00f6rdel, men den resulterande databasen \u00e4r tre g\u00e5nger mindre i storlek.<\/p>\n<p>Dessutom, baserat p\u00e5 genomf\u00f6rda tester kan slutsatsen dras att prestandaf\u00f6rlusterna \u00e4r mycket obetydliga. I vissa fall fungerar JSONB till och med snabbare \u00e4n EAV, vilket g\u00f6r det \u00e4nnu b\u00e4ttre. Men detta referenstest t\u00e4cker givetvis inte alla aspekter (t.ex. entiteter med mycket stora egenskaper, en betydande \u00f6kning av antalet egenskaper f\u00f6r existerande data,...), s\u00e5 om du har n\u00e5gra f\u00f6rslag p\u00e5 hur de kan f\u00f6rb\u00e4ttras, tveka inte att l\u00e4mna en kommentar!<br \/>\n<br \/>K\u00e4lla: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/475178\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>TL; DR: JSONB \u043c\u043e\u0436\u0435\u0442 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0441\u0445\u0435\u043c\u044b \u0411\u0414 \u0431\u0435\u0437 \u0443\u0449\u0435\u0440\u0431\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445. \u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u041f\u0440\u0438\u0432\u0435\u0434\u0435\u043c \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440, \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u0437 \u0441\u0442\u0430\u0440\u0435\u0439\u0448\u0438\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u043c\u0438\u0440\u0435 \u0440\u0435\u043b\u044f\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0411\u0414 (\u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445): \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c, \u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 (\u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b) \u044d\u0442\u043e\u0439 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438. \u041d\u043e \u043d\u0435 \u0432\u0441\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b \u043c\u043e\u0433\u0443\u0442 \u0438\u043c\u0435\u044e\u0442 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u0441\u0432\u043e\u0439\u0441\u0442\u0432, \u043a \u0442\u043e\u043c\u0443 \u0436\u0435 \u0432 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-52584","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.4 - aioseo.com -->\n\t<meta name=\"description\" content=\"TL; DR: JSONB \u043c\u043e\u0436\u0435\u0442 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0441\u0445\u0435\u043c\u044b \u0411\u0414 \u0431\u0435\u0437 \u0443\u0449\u0435\u0440\u0431\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445. \u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u041f\u0440\u0438\u0432\u0435\u0434\u0435\u043c \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440, \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u0437 \u0441\u0442\u0430\u0440\u0435\u0439\u0448\u0438\u0445.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/zamena-eav-na-jsonb-v-postgresql\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.4\" \/>\n\t\t<meta property=\"og:locale\" content=\"sv_SE\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0417\u0430\u043c\u0435\u043d\u0430 EAV \u043d\u0430 JSONB \u0432 PostgreSQL | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"TL; DR: JSONB \u043c\u043e\u0436\u0435\u0442 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0441\u0445\u0435\u043c\u044b \u0411\u0414 \u0431\u0435\u0437 \u0443\u0449\u0435\u0440\u0431\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445. \u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u041f\u0440\u0438\u0432\u0435\u0434\u0435\u043c \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440, \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u0437 \u0441\u0442\u0430\u0440\u0435\u0439\u0448\u0438\u0445.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/zamena-eav-na-jsonb-v-postgresql\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-11-11T21:00:00+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-02-18T11:00:21+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Byta ut EAV mot JSONB i PostgreSQL | ProHoster","description":"TL; DR: JSONB kan avsev\u00e4rt f\u00f6renkla utvecklingen av databasschemat utan att kompromissa med f\u00f6rfr\u00e5gningsprestanda. Introduktion Vi ger ett klassiskt exempel, antagligen ett av de \u00e4ldsta.","canonical_url":"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/zamena-eav-na-jsonb-v-postgresql","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"sv_SE","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0417\u0430\u043c\u0435\u043d\u0430 EAV \u043d\u0430 JSONB \u0432 PostgreSQL | ProHoster","og:description":"TL; DR: JSONB \u043c\u043e\u0436\u0435\u0442 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0441\u0445\u0435\u043c\u044b \u0411\u0414 \u0431\u0435\u0437 \u0443\u0449\u0435\u0440\u0431\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445. \u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u041f\u0440\u0438\u0432\u0435\u0434\u0435\u043c \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440, \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u0437 \u0441\u0442\u0430\u0440\u0435\u0439\u0448\u0438\u0445.","og:url":"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/zamena-eav-na-jsonb-v-postgresql","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-11-11T21:00:00+00:00","article:modified_time":"2020-02-18T11:00:21+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"52584","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-24 04:07:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 20:40:27","updated":"2026-01-24 04:07:19","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts\/52584","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/comments?post=52584"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts\/52584\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/media?parent=52584"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/categories?post=52584"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/tags?post=52584"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}