{"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\/de\/blog\/administrirovanie\/zamena-eav-na-jsonb-v-postgresql","title":{"rendered":"EAV durch JSONB in PostgreSQL ersetzen","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<blockquote><p>TL; DR: JSONB kann die Entwicklung von DB-Schemata erheblich vereinfachen, ohne die Abfrageleistung zu beeintr\u00e4chtigen.<\/p><\/blockquote>\n<p><\/p>\n<h3>Einf\u00fchrung<\/h3>\n<p>\nEin klassisches Beispiel, wahrscheinlich eine der \u00e4ltesten Anwendungen in der Welt der relationalen Datenbanken (Datenbank): Wir haben eine Entit\u00e4t und m\u00fcssen bestimmte Eigenschaften (Attribute) dieser Entit\u00e4t speichern. Aber nicht alle Exemplare k\u00f6nnen denselben Satz von Eigenschaften haben; zudem k\u00f6nnen in Zukunft weitere Eigenschaften hinzugef\u00fcgt werden.<\/p>\n<p>Der einfachste Weg, dieses Problem zu l\u00f6sen, besteht darin, eine Spalte in der DB-Tabelle f\u00fcr jeden Wert des Attributs zu erstellen und einfach die auszuf\u00fcllen, die f\u00fcr ein bestimmtes Exemplar der Entit\u00e4t ben\u00f6tigt werden. Gro\u00dfartig! Problem gel\u00f6st... bis deine Tabelle Millionen von Datens\u00e4tzen enth\u00e4lt und du die Notwendigkeit hast, einen neuen Datensatz hinzuzuf\u00fcgen.<\/p>\n<p>Betrachten wir das EAV-Muster (<noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Entity%E2%80%93attribute%E2%80%93value_model\">Entity-Attribute-Value<\/a><\/noindex>), das ziemlich h\u00e4ufig vorkommt. Eine Tabelle enth\u00e4lt Entit\u00e4ten (Datens\u00e4tze), eine andere Tabelle enth\u00e4lt Eigenschaftsnamen (Attribute), und eine dritte Tabelle verbindet Entit\u00e4ten mit ihren Attributen und enth\u00e4lt die Werte dieser Attribute f\u00fcr die aktuelle Entit\u00e4t. Dies erm\u00f6glicht es dir, verschiedene Eigenschaftss\u00e4tze f\u00fcr unterschiedliche Objekte zu haben und Eigenschaften \u201eon the fly\u201c hinzuzuf\u00fcgen, ohne die DB-Strukturen zu \u00e4ndern.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><br \/>\nDennoch w\u00fcrde ich diese Anmerkung nicht schreiben, wenn es keine Nachteile bei der Verwendung des EVA-Ansatzes g\u00e4be. So erfordert beispielsweise das Abrufen einer oder mehrerer Entit\u00e4ten mit jeweils 1 Attribut 2 Joins in der Abfrage: der erste \u2013 ein Join mit der Attributtabelle, der zweite \u2013 ein Join mit der Wertetabelle. Wenn eine Entit\u00e4t 2 Attribute hat, sind bereits 4 Joins erforderlich! Dar\u00fcber hinaus werden alle Attribute normalerweise als Strings gespeichert, was zu Typumwandlungen sowohl f\u00fcr das Ergebnis als auch f\u00fcr die WHERE-Klausel f\u00fchrt. Wenn Sie viele Abfragen schreiben, ist das aus Ressourcensicht recht verschwenderisch.<\/p>\n<p>Trotz dieser offensichtlichen Nachteile wird EAV schon lange zur L\u00f6sung solcher Probleme eingesetzt. Es waren unvermeidbare Nachteile, und es gab einfach keine bessere Alternative. <br \/>\nDoch dann kam eine neue \u201eTechnologie\u201c in PostgreSQL\u2026<\/p>\n<p>Seit PostgreSQL 9.4 wurde der Datentyp JSONB hinzugef\u00fcgt, um bin\u00e4re JSON-Daten zu speichern. Obwohl die Speicherung von JSON in diesem Format in der Regel etwas mehr Platz und Zeit ben\u00f6tigt als einfacher Text-JSON, sind die Operationen damit viel schneller. Au\u00dferdem unterst\u00fctzt JSONB das Indizieren, was Abfragen noch schneller macht.<\/p>\n<p>Der Datentyp JSONB erm\u00f6glicht es uns, das umst\u00e4ndliche EAV-Muster zu ersetzen, indem wir lediglich eine JSONB-Spalte zu unserer Entit\u00e4tstabelle hinzuf\u00fcgen, was das Datenbankdesign erheblich vereinfacht. Viele behaupten jedoch, dass dies mit einem R\u00fcckgang der Leistung einhergehen sollte\u2026 Aus diesem Grund ist dieser Artikel entstanden.<\/p>\n<h3>Einrichten einer Testdatenbank<\/h3>\n<p>\nF\u00fcr diesen Vergleich habe ich eine Datenbank auf einer neuen Installation von PostgreSQL 9.5 auf einem 80-Dollar-Bauteil erstellt <noindex><a rel=\"nofollow\" href=\"https:\/\/www.digitalocean.com\/\">DigitalOcean<\/a><\/noindex> Ubuntu 14.04. Nach der Anpassung einiger Parameter in postgresql.conf habe ich <noindex><a rel=\"nofollow\" href=\"https:\/\/gist.github.com\/coussej\/80c385332ce37df6687f\">diesen<\/a><\/noindex> das Skript mit psql ausgef\u00fchrt. F\u00fcr die Darstellung der Daten im EAV wurden die folgenden Tabellen erstellt:<\/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>\nUnten ist die Tabelle dargestellt, wo die gleichen Daten gespeichert werden, aber mit Attributen in der JSONB-Spalte \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>\nSieht viel einfacher aus, oder? Dann wurden 10 Millionen Datens\u00e4tze zu den Entit\u00e4tstabellen (<i>entity<\/i> &amp; <i>entity_jsonb<\/i>) hinzugef\u00fcgt, und entsprechend wurden die Tabellen, in denen das EAV-Muster und der Ansatz mit der JSONB-Spalte verwendet wird, mit denselben Daten gef\u00fcllt \u2013 <i>entity_jsonb.properties<\/i>. Damit erhielten wir mehrere verschiedene Datentypen unter all den Eigenschaften. Beispiel f\u00fcr Daten:<\/p>\n<pre><code class=\"json\">{\n  id:          1\n  name:        \"Entity1\"\n  description: \"Test-Entity Nr. 1\"\n  properties:  {\n    color:        \"rot\"\n    length:       120\n    width:        3.1882420\n    hasSomething: true\n    country:      \"Belgien\"\n  } \n}<\/code><\/pre>\n<p>\nJetzt haben wir also die gleichen Daten f\u00fcr zwei Varianten. Lassen Sie uns beginnen, die Implementierungen in der Praxis zu vergleichen!<\/p>\n<h3>Vereinfachung des Designs<\/h3>\n<p>\nEs wurde bereits erw\u00e4hnt, dass das Datenbankdesign erheblich vereinfacht wurde: eine Tabelle, durch die Verwendung der JSONB-Spalte f\u00fcr Eigenschaften, anstelle von drei Tabellen f\u00fcr EAV. Aber wie wirkt sich das auf die Abfragen aus? Die Aktualisierung einer Eigenschaft einer Entit\u00e4t sieht folgenderma\u00dfen aus:<\/p>\n<pre><code class=\"pgsql\">-- EAV\nUPDATE entity_attribute_value \nSET value = 'blau' \nWHERE entity_attribute_id = 1 \n  AND entity_id = 120;\n\n-- JSONB\nUPDATE entity_jsonb \nSET properties = jsonb_set(properties, '{\"color\"}', '\"blau\"') \nWHERE id = 120;\n<\/code><\/pre>\n<p>\nWie wir sehen, sieht die letzte Abfrage nicht einfacher aus. Um den Wert einer Eigenschaft im JSONB-Objekt zu aktualisieren, m\u00fcssen wir die Funktion <noindex><a rel=\"nofollow\" href=\"http:\/\/www.postgresql.org\/docs\/9.5\/static\/functions-json.html\">jsonb_set()<\/a><\/noindex>, und wir m\u00fcssen unseren neuen Wert als JSONB-Objekt \u00fcbergeben. Allerdings m\u00fcssen wir keinen Identifier im Voraus kennen. Schaut man sich das Beispiel mit EAV an, m\u00fcssen wir sowohl entity_id als auch entity_attribute_id kennen, um das Update durchzuf\u00fchren. Wenn Sie eine Eigenschaft in einer JSONB-Spalte basierend auf dem Objektname aktualisieren m\u00f6chten, geschieht das alles in einer einfachen Zeile.<\/p>\n<p>Jetzt lassen Sie uns die Entit\u00e4t ausw\u00e4hlen, die wir gerade basierend auf ihrer neuen Farbe aktualisiert haben:<\/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 = 'farbe' AND eav.value = 'blau';\n\n-- JSONB\nSELECT name \nFROM entity_jsonb \nWHERE properties -&gt;&gt; 'color' = 'blau';\n<\/code><\/pre>\n<p>\nIch denke, wir k\u00f6nnen uns einigen, dass die zweite Abfrage k\u00fcrzer ist (ohne Join!) und somit lesbarer. Hier gewinnt JSONB! Wir verwenden den JSON-Operator -&gt;&gt;, um die Farbe als Textwert aus dem JSONB-Objekt zu erhalten. Es gibt auch einen zweiten Weg, um dasselbe Ergebnis im JSONB-Modell mit dem Operator @&gt; zu erreichen:<\/p>\n<pre><code class=\"pgsql\">-- JSONB \nSELECT name \nFROM entity_jsonb \nWHERE properties @&gt; '{\"color\": \"blau\"}';\n<\/code><\/pre>\n<p>\nDas ist etwas komplizierter: Wir pr\u00fcfen, ob das JSON-Objekt in der Spalte Eigenschaften das Objekt enth\u00e4lt, das sich rechts vom Operator @&gt; befindet. Weniger lesbar, aber leistungsst\u00e4rker (siehe weiter unten). <\/p>\n<p>Lassen Sie uns die Verwendung von JSONB noch weiter vereinfachen, wenn Sie mehrere Eigenschaften gleichzeitig ausw\u00e4hlen m\u00fcssen. Hier passt der JSONB-Ansatz wirklich gut: Wir w\u00e4hlen einfach die Eigenschaften als zus\u00e4tzliche Spalten in unserem Ergebnisset aus, ohne Joins vornehmen zu m\u00fcssen:<\/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>\nMit EAV ben\u00f6tigen Sie 2 Joins f\u00fcr jede Eigenschaft, die Sie abfragen m\u00f6chten. Meiner Meinung nach zeigen die oben genannten Abfragen eine erhebliche Vereinfachung im Datenbankdesign. Mehr Beispiele, wie man Abfragen an JSONB schreibt, finden Sie m\u00f6glicherweise auch in <noindex><a rel=\"nofollow\" href=\"http:\/\/schinckel.net\/2014\/05\/25\/querying-json-in-postgres\/\">das<\/a><\/noindex> dem Beitrag.<br \/>\nJetzt ist es an der Zeit, \u00fcber die Leistung zu sprechen.<\/p>\n<h3>Leistung<\/h3>\n<p>\nUm die Leistung zu vergleichen, habe ich <noindex><a rel=\"nofollow\" href=\"http:\/\/www.postgresql.org\/docs\/9.1\/static\/sql-explain.html\">EXPLAIN ANALYZE<\/a><\/noindex> In den Abfragen zur Berechnung der Ausf\u00fchrungszeit. Jede Abfrage wurde mindestens dreimal ausgef\u00fchrt, da der Abfrageplaner beim ersten Mal mehr Zeit ben\u00f6tigt. Zuerst habe ich die Abfragen ohne jegliche Indizes ausgef\u00fchrt. Offensichtlich hatte dies einen Vorteil f\u00fcr JSONB, da die Joins, die f\u00fcr EAV erforderlich sind, keine Indizes verwenden konnten (die Fremdschl\u00fcssel-Felder waren nicht indiziert). Danach habe ich einen Index f\u00fcr die 2 externen Schl\u00fcsselspalten der EAV-Wertetabelle sowie einen Index erstellt. <noindex><a rel=\"nofollow\" href=\"http:\/\/www.postgresql.org\/docs\/9.1\/static\/textsearch-indexes.html\">GIN<\/a><\/noindex> f\u00fcr die JSONB-Spalte.<\/p>\n<p>Die Datenaktualisierungen zeigten die folgenden Ergebnisse hinsichtlich der Zeit (in ms). Bitte beachten Sie, dass die Skala logarithmisch ist:<\/p>\n<p><img decoding=\"async\" alt=\"EAV durch JSONB in PostgreSQL ersetzen\" src=\"\/wp-content\/uploads\/2019\/11\/8a12ccd7a46d04868b1cc5fcaf01a581.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nWir sehen, dass JSONB viel schneller (&gt; 50000-x) als EAV ist, wenn keine Indizes verwendet werden, aus den oben genannten Gr\u00fcnden. Wenn wir die Spalten mit Prim\u00e4rschl\u00fcsseln indizieren, verschwindet der Unterschied fast, aber JSONB ist immer noch 1,3-mal schneller als EAV. Beachten Sie, dass der Index in der JSONB-Spalte hier keinen Einfluss hat, da wir die Eigenschaften-Spalte in den Bewertungskriterien nicht verwenden. <\/p>\n<p>F\u00fcr die Auswahl von Daten basierend auf dem Wert von Eigenschaften erhalten wir die folgenden Ergebnisse (normale Skala):<\/p>\n<p><img decoding=\"async\" alt=\"EAV durch JSONB in PostgreSQL ersetzen\" src=\"\/wp-content\/uploads\/2019\/11\/e9a1fd797ef60132e661da686f6214a3.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEs ist zu erkennen, dass JSONB erneut schneller arbeitet als EAV ohne Indizes, aber wenn EAV mit Indizes arbeitet, ist es dennoch schneller als JSONB. Dann habe ich gesehen, dass die Zeit f\u00fcr JSONB-Abfragen gleich war, was mich auf die Tatsache aufmerksam machte, dass der GIN-Index nicht greift. Offenbar funktioniert der GIN-Index f\u00fcr Spalten mit ausgef\u00fcllten Eigenschaften nur bei der Verwendung des Einschlussoperators @&gt;. Ich nutzte dies in einem neuen Test, was einen enormen Einfluss auf die Zeit hatte: nur 0,153 ms! Das ist 15000-mal schneller als EAV und 25000-mal schneller als der Operator -&gt;&gt;. <\/p>\n<p>Ich denke, das war schnell genug!<\/p>\n<h3>Gr\u00f6\u00dfe der Datenbanktabellen<\/h3>\n<p>\nLassen Sie uns die Gr\u00f6\u00dfen der Tabellen bei beiden Ans\u00e4tzen vergleichen. In psql k\u00f6nnen wir die Gr\u00f6\u00dfe aller Tabellen und Indizes mit dem Befehl <b>dti+<\/b><\/p>\n<p><img decoding=\"async\" alt=\"EAV durch JSONB in PostgreSQL ersetzen\" src=\"\/wp-content\/uploads\/2019\/11\/c6c1fe7901fe9ae2bd446cf4ae99b923.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nF\u00fcr den EAV-Ansatz betragen die Tabellengr\u00f6\u00dfen etwa 3068 MB, und die Indizes bis zu 3427 MB, was insgesamt 6,43 GB ergibt. Bei Verwendung des JSONB-Ansatzes werden 1817 MB f\u00fcr die Tabelle und 318 MB f\u00fcr die Indizes verwendet, was 2,08 GB ergibt. Das ist dreimal weniger! Diese Tatsache hat mich etwas \u00fcberrascht, da wir die Eigenschaften in jedem JSONB-Objekt speichern. <\/p>\n<p>Aber die Zahlen sprechen f\u00fcr sich selbst: In EAV speichern wir 2 Ganzzahl-Fremdschl\u00fcssel auf Attributwerte, was zu 8 zus\u00e4tzlichen Bytes an Daten f\u00fchrt. Dar\u00fcber hinaus werden in EAV alle Eigenschaftswerte als Text gespeichert, w\u00e4hrend JSONB numerische und boolesche Werte verwendet, wo dies m\u00f6glich ist, was zu einem geringeren Volumen f\u00fchrt.<\/p>\n<h3>Ergebnisse<\/h3>\n<p>\nInsgesamt denke ich, dass die Speicherung von Entit\u00e4tseigenschaften im JSONB-Format das Design und die Wartung Ihrer Datenbank erheblich vereinfachen kann. Wenn Sie viele Abfragen durchf\u00fchren, wird alles, was in einer Tabelle mit der Entit\u00e4t gespeichert ist, tats\u00e4chlich effizienter funktionieren. Und die Tatsache, dass es die Interaktion zwischen den Daten vereinfacht, ist bereits ein Vorteil, aber auch die resultierende Datenbank hat ein Volumen, das dreimal kleiner ist.<\/p>\n<p>Auch aus den durchgef\u00fchrten Tests l\u00e4sst sich zusammenfassen, dass die Leistungseinbu\u00dfen sehr geringf\u00fcgig sind. In einigen F\u00e4llen funktioniert JSONB sogar schneller als EAV, was es noch besser macht. Allerdings deckt dieser Benchmark-Test nat\u00fcrlich nicht alle Aspekte ab (zum Beispiel Entit\u00e4ten mit einer sehr gro\u00dfen Anzahl von Eigenschaften, signifikantem Anstieg der Eigenschaften vorhandener Daten,\u2026), daher, wenn Sie Vorschl\u00e4ge haben, wie man sie verbessern kann, z\u00f6gern Sie bitte nicht, sie in den Kommentaren zu hinterlassen!<br \/>\n<br \/>Quelle: <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.1.1 - 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\/de\/blog\/administrirovanie\/zamena-eav-na-jsonb-v-postgresql\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"de_DE\" \/>\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\/de\/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\udd47EAV durch JSONB in PostgreSQL ersetzen | ProHoster","description":"TL; DR: JSONB kann die Erstellung von Datenbankschemas erheblich vereinfachen, ohne die Abfrageleistung zu beeintr\u00e4chtigen. Einleitung Wir bringen ein klassisches Beispiel, wahrscheinlich eines der \u00e4ltesten.","canonical_url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/zamena-eav-na-jsonb-v-postgresql","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"de_DE","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\/de\/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\/de\/wp-json\/wp\/v2\/posts\/52584","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/comments?post=52584"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/52584\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media?parent=52584"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/categories?post=52584"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/tags?post=52584"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}