{"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\/da\/blog\/administrirovanie\/zamena-eav-na-jsonb-v-postgresql","title":{"rendered":"Erstatning af EAV med JSONB i PostgreSQL","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<blockquote><p>TL; DR: JSONB kan betydeligt forenkle udviklingen af en database-scheme uden at g\u00e5 p\u00e5 kompromis med ydeevnen i foresp\u00f8rgsler.<\/p><\/blockquote>\n<p><\/p>\n<h3>Introduktion<\/h3>\n<p>\nLad os kigge p\u00e5 et klassisk eksempel, m\u00e5ske en af de \u00e6ldste anvendelser i verden af relationelle databaser (database): vi har en entitet, og det er n\u00f8dvendigt at gemme bestemte egenskaber (attributter) for denne entitet. Men ikke alle instanser kan have det samme s\u00e6t af egenskaber, og derudover kan det v\u00e6re muligt at tilf\u00f8je flere egenskaber i fremtiden.<\/p>\n<p>Den nemmeste m\u00e5de at l\u00f8se dette problem p\u00e5 er at oprette en kolonne i databasen for hver egenskabsv\u00e6rdi og blot udfylde dem, der er n\u00f8dvendige for den specifikke instans af entiteten. Godt! Problemet er l\u00f8st\u2026 indtil din tabel indeholder millioner af poster, og du f\u00e5r behov for at tilf\u00f8je en ny post.<\/p>\n<p>Lad os overveje EAV-m\u00f8nsteret (<noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Entity%E2%80%93attribute%E2%80%93value_model\">Entity-Attribute-Value<\/a><\/noindex>), som forekommer ret ofte. \u00c9n tabel indeholder entiteter (poster), en anden tabel indeholder navne p\u00e5 egenskaber (attributter), og en tredje tabel forbinder entiteter med deres attributter og indeholder v\u00e6rdien af disse attributter for den aktuelle entitet. Dette giver dig mulighed for at have forskellige s\u00e6t af egenskaber for forskellige objekter og tilf\u00f8je egenskaber \"on the fly\", uden at \u00e6ndre databasen.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><br \/>\nAlligevel ville jeg ikke skrive denne bem\u00e6rkning, hvis der ikke var ulemper ved brugen af EVA-tilgangen. For eksempel kr\u00e6ves der 2 joins i foresp\u00f8rgslen for at hente en eller flere enheder, der har hver 1 attribut: f\u00f8rst en joining med attributtabellen, derefter en joining med v\u00e6rditabellen. Hvis enheden har 2 attributter, kr\u00e6ves der allerede 4 joins! Derudover lagres alle attributter normalt som strenge, hvilket medf\u00f8rer typekonvertering b\u00e5de for resultatet og for WHERE-betingelsen. Hvis du skriver mange foresp\u00f8rgsler, er det temmelig spild af ressourcer.<\/p>\n<p>P\u00e5 trods af disse \u00e5benlyse ulemper har EAV l\u00e6nge v\u00e6ret brugt til at l\u00f8se denne type problemer. Det var uundg\u00e5elige ulemper, og der var simpelthen ikke en bedre alternativ. <br \/>\nMen s\u00e5 kom der en ny \"teknologi\" i PostgreSQL...<\/p>\n<p>Fra PostgreSQL 9.4 blev datatypen JSONB tilf\u00f8jet for at opbevare bin\u00e6re JSON-data. Selvom opbevaring af JSON i dette format normalt kr\u00e6ver lidt mere plads og tid end almindelig tekst-JSON, s\u00e5 er udf\u00f8relsen af operationer med det meget hurtigere. JSONB underst\u00f8tter ogs\u00e5 indeksering, hvilket g\u00f8r foresp\u00f8rgsler til det endnu hurtigere.<\/p>\n<p>Datatypen JSONB giver os mulighed for at erstatte det omfangsrige EAV-m\u00f8nster ved blot at tilf\u00f8je \u00e9n JSONB-kolonne i vores entitetstabel, hvilket i h\u00f8j grad forenkler database-udformningen. Men mange h\u00e6vder, at dette b\u00f8r ledsages af et fald i ydeevnen... Derfor blev denne artikel til.<\/p>\n<h3>Ops\u00e6tning af testdatabase<\/h3>\n<p>\nTil denne sammenligning har jeg oprettet en database p\u00e5 en ny installation af PostgreSQL 9.5 p\u00e5 en 80-dollars ops\u00e6tning <noindex><a rel=\"nofollow\" href=\"https:\/\/www.digitalocean.com\/\">DigitalOcean<\/a><\/noindex> Ubuntu 14.04. Efter at have justeret nogle indstillinger i postgresql.conf, k\u00f8rte jeg <noindex><a rel=\"nofollow\" href=\"https:\/\/gist.github.com\/coussej\/80c385332ce37df6687f\">denne<\/a><\/noindex> scriptet ved hj\u00e6lp af psql. For at repr\u00e6sentere data i EAV-format blev f\u00f8lgende tabeller oprettet:<\/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>\nNedenfor er en tabel, hvor de samme data vil blive opbevaret, men med attributter i en JSONB-kolonne \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>\nDet ser meget lettere ud, ikke? Derefter blev der tilf\u00f8jet 10 millioner poster til entitetstabellerne (<i>entity<\/i> &amp; <i>entity_jsonb<\/i>) og tilsvarende blev tabellerne, hvor EAV-m\u00f8nsteret bruges, fyldt med ens data som JSONB-kolonnen \u2013 <i>entity_jsonb.properties<\/i>. P\u00e5 den m\u00e5de fik vi flere forskellige datatyper blandt hele m\u00e6ngden af egenskaber. Eksempeldata:<\/p>\n<pre><code class=\"json\">{\n  id:          1\n  name:        \"Entity1\"\n  description: \"Test entity nr. 1\"\n  properties:  {\n    color:        \"red\"\n    lenght:       120\n    width:        3.1882420\n    hassomething: true\n    country:      \"Belgium\"\n  } \n}<\/code><\/pre>\n<p>\nS\u00e5 nu har vi ens data til de to varianter. Lad os begynde at sammenligne implementeringerne i praksis!<\/p>\n<h3>Forenkling af design<\/h3>\n<p>\nDet er allerede blevet n\u00e6vnt, at designet af databasen er blevet markant forenklet: \u00e9n tabel, ved at bruge en JSONB-kolonne til egenskaber i stedet for at bruge tre tabeller til EAV. Men hvordan p\u00e5virker det foresp\u00f8rgslerne? Opdatering af en egenskab ved en entitet ser s\u00e5ledes ud:<\/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 kan se, ser den sidste foresp\u00f8rgsel ikke ligefrem enklere ud. For at opdatere v\u00e6rdien af en egenskab i et JSONB-objekt skal vi bruge funktionen <noindex><a rel=\"nofollow\" href=\"http:\/\/www.postgresql.org\/docs\/9.5\/static\/functions-json.html\">jsonb_set()<\/a><\/noindex>, og vi skal overf\u00f8re vores nye v\u00e6rdien som et JSONB-objekt. Det er dog ikke n\u00f8dvendigt at kende nogen identifikator p\u00e5 forh\u00e5nd. Ved at se p\u00e5 EAV-eksemplet skal vi vide b\u00e5de entity_id og entity_attribute_id for at udf\u00f8re opdateringen. Hvis du \u00f8nsker at opdatere en egenskab i JSONB-kolonnen baseret p\u00e5 objektnavnet, \u2013 s\u00e5 g\u00f8res alt dette i en simpel s\u00e6tning.<\/p>\n<p>Lad os nu v\u00e6lge den enhed, vi lige har opdateret, efter betingelsen for dens nye farve:<\/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>\nJeg tror, vi kan blive enige om, at det andet er kortere (uden join!), og dermed mere l\u00e6sbart. Her vinder JSONB! Vi bruger JSON-operatoren -&gt;&gt;, for at hente farven som tekstv\u00e6rdi fra JSONB-objektet. Der er ogs\u00e5 en anden m\u00e5de at opn\u00e5 det samme resultat i JSONB-modellen ved hj\u00e6lp af operatoren @&gt;:<\/p>\n<pre><code class=\"pgsql\">-- JSONB \nSELECT name \nFROM entity_jsonb \nWHERE properties @&gt; '{\"color\": \"bl\u00e5\"}';\n<\/code><\/pre>\n<p>\nDette er lidt mere komplekst: vi kontrollerer, om JSON-objektet i egenskabskolonnen indeholder objektet til h\u00f8jre for operatoren @&gt;. Mindre l\u00e6sbart, men mere effektivt (se videre). <\/p>\n<p>Lad os forsimple brugen af JSONB endnu mere, n\u00e5r du har brug for at v\u00e6lge flere egenskaber samtidigt. Det er her, JSONB-tilgangen virkelig skinner: vi v\u00e6lger blot egenskaberne som ekstra kolonner i vores resultats\u00e6t uden behov for joins:<\/p>\n<pre><code class=\"pgsql\">-- JSONB \nSELECT name\n  , properties -&gt;&gt; 'color'\n  , properties -&gt;&gt; 'land'\nFROM entity_jsonb \nWHERE id = 120;\n<\/code><\/pre>\n<p>\nMed EAV skal du have 2 joins for hver egenskab, du \u00f8nsker at foresp\u00f8rge. Efter min mening viser ovenst\u00e5ende foresp\u00f8rgsler en betydelig forenkling i designet af databasen. Du kan ogs\u00e5 finde flere eksempler p\u00e5, hvordan man skriver foresp\u00f8rgsler til JSONB i <noindex><a rel=\"nofollow\" href=\"http:\/\/schinckel.net\/2014\/05\/25\/querying-json-in-postgres\/\">denne<\/a><\/noindex> indl\u00e6gget.<br \/>\nNu er det tid til at tale om ydeevne.<\/p>\n<h3>Ydeevne<\/h3>\n<p>\nFor at sammenligne ydeevnen har jeg brugt <noindex><a rel=\"nofollow\" href=\"http:\/\/www.postgresql.org\/docs\/9.1\/static\/sql-explain.html\">EXPLAIN ANALYZE<\/a><\/noindex> i foresp\u00f8rgsler for at beregne udf\u00f8relsestid. Hver foresp\u00f8rgsel blev udf\u00f8rt mindst tre gange, fordi planl\u00e6ggeren kr\u00e6ver mere tid f\u00f8rste gang. F\u00f8rst udf\u00f8rte jeg foresp\u00f8rgsler uden indekser. Det gav tydeligvis en fordel for JSONB, da de join, der er n\u00f8dvendige for EAV, ikke kunne bruge indekser (feltet for fremmedn\u00f8gle var ikke indekseret). Herefter oprettede jeg et indeks for to kolonner med fremmedn\u00f8gler i EAV-v\u00e6rditabellen samt et indeks <noindex><a rel=\"nofollow\" href=\"http:\/\/www.postgresql.org\/docs\/9.1\/static\/textsearch-indexes.html\">GIN<\/a><\/noindex> for JSONB-kolonnen.<\/p>\n<p>Opdateringer af data viste f\u00f8lgende resultater i tid (i ms). Bem\u00e6rk, at skalaen er logaritmisk:<\/p>\n<p><img decoding=\"async\" alt=\"Erstatning af EAV med JSONB i PostgreSQL\" src=\"\/wp-content\/uploads\/2019\/11\/8a12ccd7a46d04868b1cc5fcaf01a581.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nVi ser, at JSONB er meget (&gt; 50000-x) hurtigere end EAV, n\u00e5r der ikke bruges indekser, af den grund, der er n\u00e6vnt ovenfor. N\u00e5r vi indekserer kolonner med prim\u00e6re n\u00f8gler, n\u00e6sten forsvinder forskellen, men JSONB er stadig 1,3 gange hurtigere end EAV. Bem\u00e6rk, at indekset i JSONB-kolonnen her ikke har nogen indflydelse, da vi ikke bruger egenskabsfeltet i evalueringskriterierne. <\/p>\n<p>For at v\u00e6lge data baseret p\u00e5 egenskabsv\u00e6rdi f\u00e5r vi f\u00f8lgende resultater (normal skala):<\/p>\n<p><img decoding=\"async\" alt=\"Erstatning af EAV med JSONB i PostgreSQL\" src=\"\/wp-content\/uploads\/2019\/11\/e9a1fd797ef60132e661da686f6214a3.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nMan kan m\u00e6rke, at JSONB igen fungerer hurtigere end EAV uden indekser, men n\u00e5r EAV har indekser, er det stadig hurtigere end JSONB. Men s\u00e5 s\u00e5 jeg, at tiden for JSONB-foresp\u00f8rgsler var den samme, hvilket fik mig til at indse, at GIN-indekset ikke aktiverede. Tilsyneladende, n\u00e5r du bruger GIN-indeks for en kolonne med udfyldte egenskaber, virker det kun ved brug af inkluderingsoperatoren @&gt;. Jeg brugte dette i en ny test, hvilket havde en enorm indflydelse p\u00e5 tiden: kun 0,153 ms! Det er 15000 gange hurtigere end EAV, og 25000 gange hurtigere end operatoren -&gt;&gt;. <\/p>\n<p>Jeg synes, det var hurtigt nok!<\/p>\n<h3>St\u00f8rrelsen p\u00e5 databaserne<\/h3>\n<p>\nLad os sammenligne st\u00f8rrelsen af tabellerne under begge tilgange. I psql kan vi vise st\u00f8rrelsen af alle tabeller og indekser med kommandoen <b>dti+<\/b><\/p>\n<p><img decoding=\"async\" alt=\"Erstatning af EAV med JSONB i PostgreSQL\" src=\"\/wp-content\/uploads\/2019\/11\/c6c1fe7901fe9ae2bd446cf4ae99b923.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nFor EAV-tilgangen udg\u00f8r st\u00f8rrelsen p\u00e5 tabellerne cirka 3068 MB, og indekserne op til 3427 MB, hvilket giver en samlet st\u00f8rrelse p\u00e5 6,43 GB. Ved brug af JSONB-tilgangen bruges 1817 MB til tabellen og 318 MB til indekserne, hvilket udg\u00f8r 2,08 GB. Det er tre gange mindre! Denne kendsgerning overraskede mig lidt, fordi vi gemmer egenskabsnavne i hvert JSONB-objekt. <\/p>\n<p>Men tallene taler for sig selv: i EAV opbevarer vi 2 heltals udenlandske n\u00f8gler til attributv\u00e6rdien, hvilket resulterer i 8 bytes ekstra data. Desuden opbevares alle egenskaber i EAV som tekst, mens JSONB vil bruge numeriske og logiske v\u00e6rdier, hvor det er muligt, hvilket resulterer i en mindre m\u00e6ngde.<\/p>\n<h3>Resum\u00e9<\/h3>\n<p>\nGenerelt mener jeg, at opbevaring af egenskaber for entiteter i JSONB-format kan forenkle design og vedligeholdelse af din database betydeligt. Hvis du udf\u00f8rer mange foresp\u00f8rgsler, vil alt, hvad der opbevares i \u00e9n tabel med en entitet, virkelig fungere mere effektivt. Og det faktum, at det forenkler interaktionen mellem data allerede er en fordel, men ogs\u00e5 den resulterende database er 3 gange mindre i volumen.<\/p>\n<p>Desuden, if\u00f8lge de udf\u00f8rte tests, kan vi konkludere, at tabet af ydeevne er meget ubetydeligt. I nogle tilf\u00e6lde fungerer JSONB endda hurtigere end EAV, hvilket g\u00f8r det endnu bedre. Dog d\u00e6kker denne benchmarktest selvf\u00f8lgelig ikke alle aspekter (for eksempel entiteter med et meget stort antal egenskaber, betydelige stigninger i antallet af eksisterende egenskaber,...), s\u00e5 hvis du har nogen forslag til, hvordan de kan forbedres, s\u00e5 t\u00f8v ikke med at skrive det i kommentarerne!<br \/>\n<br \/>Kilde: <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.3 - 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\/da\/blog\/administrirovanie\/zamena-eav-na-jsonb-v-postgresql\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"da_DK\" \/>\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\/da\/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\udd47Udskiftning af EAV med JSONB i PostgreSQL | ProHoster","description":"TL; DR: JSONB kan v\u00e6sentligt forenkle udviklingen af database-skemaer uden at g\u00e5 p\u00e5 kompromis med ydeevnen i foresp\u00f8rgsler. Introduktion Vi vil give et klassisk eksempel, sandsynligvis et af de \u00e6ldste.","canonical_url":"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/zamena-eav-na-jsonb-v-postgresql","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"da_DK","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\/da\/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\/da\/wp-json\/wp\/v2\/posts\/52584","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/comments?post=52584"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/52584\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media?parent=52584"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/categories?post=52584"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/tags?post=52584"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}