{"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\/fr\/blog\/administrirovanie\/zamena-eav-na-jsonb-v-postgresql","title":{"rendered":"Remplacement de EAV par JSONB dans PostgreSQL","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<blockquote><p>TL; DR : JSONB peut simplifier consid\u00e9rablement le d\u00e9veloppement du sch\u00e9ma de base de donn\u00e9es sans compromettre la performance des requ\u00eates.<\/p><\/blockquote>\n<p><\/p>\n<h3>Introduction<\/h3>\n<p>\nPrenons un exemple classique, probablement l'une des plus anciennes utilisations dans le monde des bases de donn\u00e9es relationnelles : nous avons une entit\u00e9 et devons conserver certaines propri\u00e9t\u00e9s (attributs) de cette entit\u00e9. Mais tous les exemples peuvent ne pas avoir le m\u00eame ensemble de propri\u00e9t\u00e9s, et il est \u00e9galement possible d'ajouter d'autres propri\u00e9t\u00e9s \u00e0 l'avenir.<\/p>\n<p>La mani\u00e8re la plus simple de r\u00e9soudre ce probl\u00e8me est de cr\u00e9er une colonne dans la table de la base de donn\u00e9es pour chaque valeur de propri\u00e9t\u00e9 et de simplement remplir celles qui sont n\u00e9cessaires pour un exemple sp\u00e9cifique de l'entit\u00e9. Excellent ! Probl\u00e8me r\u00e9solu \u2026 jusqu'\u00e0 ce que votre table contienne des millions d'enregistrements et que vous deviez ajouter un nouvel enregistrement.<\/p>\n<p>Consid\u00e9rons le mod\u00e8le EAV (<noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Entity%E2%80%93attribute%E2%80%93value_model\">Entity-Attribute-Value<\/a><\/noindex>), qui est assez courant. Une table contient des entit\u00e9s (enregistrements), une autre table contient les noms des propri\u00e9t\u00e9s (attributs) et une troisi\u00e8me table lie les entit\u00e9s \u00e0 leurs attributs et contient la valeur de ces attributs pour l'entit\u00e9 actuelle. Cela vous permet d'avoir diff\u00e9rents ensembles de propri\u00e9t\u00e9s pour diff\u00e9rents objets, ainsi que d'ajouter des propri\u00e9t\u00e9s \"\u00e0 la vol\u00e9e\", sans modifier la structure de la base de donn\u00e9es.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><br \/>\nCependant, je ne r\u00e9digerais pas cette note s'il n'y avait pas de d\u00e9fauts dans l'approche utilisant EVA. Par exemple, pour obtenir une ou plusieurs entit\u00e9s, chacune ayant un attribut, il faut 2 jointures dans la requ\u00eate : la premi\u00e8re \u2013 une jointure avec la table des attributs, la seconde \u2013 une jointure avec la table des valeurs. Si l'entit\u00e9 a 2 attributs, il en faut d\u00e9j\u00e0 4 ! De plus, tous les attributs sont g\u00e9n\u00e9ralement stock\u00e9s sous forme de cha\u00eenes, ce qui entra\u00eene une conversion des types, tant pour le r\u00e9sultat que pour la condition WHERE. Si vous \u00e9crivez beaucoup de requ\u00eates, cela devient assez co\u00fbteux en termes d'utilisation des ressources.<\/p>\n<p>Malgr\u00e9 ces inconv\u00e9nients \u00e9vidents, EAV est depuis longtemps utilis\u00e9 pour r\u00e9soudre ce type de probl\u00e8mes. Ce sont des inconv\u00e9nients in\u00e9vitables, et il n'y avait tout simplement pas de meilleure alternative. <br \/>\nMais ensuite, une nouvelle \"technologie\" est apparue dans PostgreSQL\u2026<\/p>\n<p>\u00c0 partir de PostgreSQL 9.4, un type de donn\u00e9es JSONB a \u00e9t\u00e9 ajout\u00e9 pour stocker des donn\u00e9es JSON binaires. Bien que le stockage de JSON dans ce format prenne g\u00e9n\u00e9ralement un peu plus d'espace et de temps que le JSON en texte brut, les op\u00e9rations effectu\u00e9es sur celles-ci se font beaucoup plus rapidement. De plus, JSONB prend en charge l'indexation, ce qui rend les requ\u00eates encore plus rapides.<\/p>\n<p>Le type de donn\u00e9es JSONB nous permet de remplacer le mod\u00e8le EAV encombrant en ajoutant simplement une colonne JSONB dans notre table d'entit\u00e9s, ce qui simplifie consid\u00e9rablement la conception de la base de donn\u00e9es. Mais beaucoup soutiennent que cela doit s'accompagner d'une baisse des performances\u2026 C'est pour cette raison que cet article a \u00e9t\u00e9 \u00e9crit.<\/p>\n<h3>Configuration de la base de donn\u00e9es de test<\/h3>\n<p>\nPour cette comparaison, j'ai cr\u00e9\u00e9 une base de donn\u00e9es sur une nouvelle installation de PostgreSQL 9.5 sur une machine \u00e0 80 dollars. <noindex><a rel=\"nofollow\" href=\"https:\/\/www.digitalocean.com\/\">DigitalOcean<\/a><\/noindex> Ubuntu 14.04. Apr\u00e8s avoir configur\u00e9 certains param\u00e8tres dans postgresql.conf, j'ai ex\u00e9cut\u00e9 <noindex><a rel=\"nofollow\" href=\"https:\/\/gist.github.com\/coussej\/80c385332ce37df6687f\">celui-ci<\/a><\/noindex> le script \u00e0 l'aide de psql. Pour repr\u00e9senter les donn\u00e9es sous forme EAV, les tables suivantes ont \u00e9t\u00e9 cr\u00e9\u00e9es :<\/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>\nCi-dessous se trouve une table o\u00f9 seront stock\u00e9es les m\u00eames donn\u00e9es, mais avec des attributs dans une colonne de type JSONB \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>\nCela semble beaucoup plus simple, n'est-ce pas ? Ensuite, 10 millions d'enregistrements ont \u00e9t\u00e9 ajout\u00e9s aux tables d'entit\u00e9s (<i>entity<\/i> &amp; <i>entity_jsonb<\/i>) et, en cons\u00e9quence, les donn\u00e9es identiques ont \u00e9t\u00e9 peupl\u00e9es dans les tables o\u00f9 le mod\u00e8le EAV est utilis\u00e9 et celles avec la colonne JSONB \u2013 <i>entity_jsonb.properties<\/i>. Ainsi, nous avons obtenu plusieurs types de donn\u00e9es diff\u00e9rents parmi l'ensemble des propri\u00e9t\u00e9s. Exemple de donn\u00e9es :<\/p>\n<pre><code class=\"json\">{\n  id:          1\n  name:        \"Entity1\"\n  description: \"Test entity no. 1\"\n  properties:  {\n    color:        \"rouge\"\n    lenght:       120\n    width:        3.1882420\n    hassomething: true\n    country:      \"Belgique\"\n  } \n}<\/code><\/pre>\n<p>\nAinsi, nous avons maintenant des donn\u00e9es identiques pour les deux variantes. Commen\u00e7ons \u00e0 comparer les impl\u00e9mentations en action !<\/p>\n<h3>Simplification de la conception<\/h3>\n<p>\nIl a d\u00e9j\u00e0 \u00e9t\u00e9 mentionn\u00e9 que la conception de la base de donn\u00e9es a \u00e9t\u00e9 consid\u00e9rablement simplifi\u00e9e : une seule table, gr\u00e2ce \u00e0 l'utilisation de la colonne JSONB pour les propri\u00e9t\u00e9s, au lieu de trois tables pour EAV. Mais comment cela se refl\u00e8te-t-il dans les requ\u00eates ? La mise \u00e0 jour d'une propri\u00e9t\u00e9 d'une entit\u00e9 se pr\u00e9sente comme suit :<\/p>\n<pre><code class=\"pgsql\">-- EAV\nUPDATE entity_attribute_value \nSET value = 'blue' \nWHERE entity_attribute_id = 1 \n  AND entity_id = 120;\n\n-- JSONB\nUPDATE entity_jsonb \nSET properties = jsonb_set(properties, '{\"color\"}', '\"blue\"') \nWHERE id = 120;\n<\/code><\/pre>\n<p>\nComme nous le voyons, la derni\u00e8re requ\u00eate ne semble pas plus simple. Pour mettre \u00e0 jour la valeur d'une propri\u00e9t\u00e9 dans un objet JSONB, nous devons utiliser la fonction <noindex><a rel=\"nofollow\" href=\"http:\/\/www.postgresql.org\/docs\/9.5\/static\/functions-json.html\">jsonb_set()<\/a><\/noindex>, et nous devons passer notre nouvelle valeur sous forme d'objet JSONB. Cependant, nous n'avons pas besoin de conna\u00eetre d'identifiant \u00e0 l'avance. En regardant l'exemple avec EAV, nous devons conna\u00eetre \u00e0 la fois entity_id et entity_attribute_id pour effectuer la mise \u00e0 jour. Si vous souhaitez mettre \u00e0 jour une propri\u00e9t\u00e9 dans la colonne JSONB en fonction du nom de l'objet, cela se fait en une seule ligne simple.<\/p>\n<p>Maintenant, s\u00e9lectionnons l'entit\u00e9 que nous venons de mettre \u00e0 jour, en fonction de sa nouvelle couleur :<\/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 = 'blue';\n\n-- JSONB\nSELECT name \nFROM entity_jsonb \nWHERE properties -&gt;&gt; 'color' = 'blue';\n<\/code><\/pre>\n<p>\nJe pense que nous pouvons convenir que la seconde est plus courte (sans jointure !), et donc plus lisible. Ici, la victoire est \u00e0 JSONB ! Nous utilisons l'op\u00e9rateur JSON -&gt;&gt; pour obtenir la couleur comme valeur texte de l'objet JSONB. Il existe \u00e9galement une seconde m\u00e9thode pour obtenir le m\u00eame r\u00e9sultat dans le mod\u00e8le JSONB en utilisant l'op\u00e9rateur @&gt; :<\/p>\n<pre><code class=\"pgsql\">-- JSONB \nSELECT name \nFROM entity_jsonb \nWHERE properties @&gt; '{\"color\": \"blue\"}';\n<\/code><\/pre>\n<p>\nC'est un peu plus compliqu\u00e9 : nous v\u00e9rifions si l'objet JSON dans la colonne des propri\u00e9t\u00e9s contient l'objet qui se trouve \u00e0 droite de l'op\u00e9rateur @&gt;. Moins lisible, plus performant (voir ci-dessous). <\/p>\n<p>Simplifions l'utilisation de JSONB encore plus quand vous devez s\u00e9lectionner plusieurs propri\u00e9t\u00e9s en m\u00eame temps. C'est l\u00e0 que l'approche JSONB est vraiment adapt\u00e9e : nous choisissons simplement les propri\u00e9t\u00e9s comme colonnes suppl\u00e9mentaires dans notre ensemble de r\u00e9sultats sans n\u00e9cessiter de jointures :<\/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>\nAvec EAV, vous aurez besoin de 2 jointures pour chaque propri\u00e9t\u00e9 que vous souhaitez interroger. \u00c0 mon avis, les requ\u00eates ci-dessus montrent un grand simplification dans la conception de la base de donn\u00e9es. Vous pouvez \u00e9galement voir plus d'exemples de requ\u00eates JSONB dans <noindex><a rel=\"nofollow\" href=\"http:\/\/schinckel.net\/2014\/05\/25\/querying-json-in-postgres\/\">ce<\/a><\/noindex> ce post.<br \/>\nMaintenant, il est temps de parler des performances.<\/p>\n<h3>Performance<\/h3>\n<p>\nPour comparer les performances, j'ai utilis\u00e9 <noindex><a rel=\"nofollow\" href=\"http:\/\/www.postgresql.org\/docs\/9.1\/static\/sql-explain.html\">EXPLAIN ANALYZE<\/a><\/noindex> dans les requ\u00eates, pour le calcul du temps d'ex\u00e9cution. Chaque requ\u00eate a \u00e9t\u00e9 ex\u00e9cut\u00e9e au moins trois fois, car le planificateur de requ\u00eates n\u00e9cessite plus de temps lors de la premi\u00e8re ex\u00e9cution. Tout d'abord, j'ai ex\u00e9cut\u00e9 les requ\u00eates sans aucun index. \u00c9videmment, cela a \u00e9t\u00e9 un avantage pour JSONB, puisque les jointures n\u00e9cessaires pour EAV ne pouvaient pas utiliser d'index (les champs de cl\u00e9 \u00e9trang\u00e8re n'\u00e9taient pas index\u00e9s). Apr\u00e8s cela, j'ai cr\u00e9\u00e9 un index pour 2 colonnes de cl\u00e9s \u00e9trang\u00e8res dans la table des valeurs EAV, ainsi qu'un index <noindex><a rel=\"nofollow\" href=\"http:\/\/www.postgresql.org\/docs\/9.1\/static\/textsearch-indexes.html\">GIN<\/a><\/noindex> pour la colonne JSONB.<\/p>\n<p>Les mises \u00e0 jour de donn\u00e9es ont montr\u00e9 les r\u00e9sultats suivants en termes de temps (en ms). Notez que l'\u00e9chelle est logarithmique :<\/p>\n<p><img decoding=\"async\" alt=\"Remplacement de EAV par JSONB dans PostgreSQL\" src=\"\/wp-content\/uploads\/2019\/11\/8a12ccd7a46d04868b1cc5fcaf01a581.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNous constatons que JSONB est de loin (&gt; 50000 fois) plus rapide que EAV lorsqu'aucun index n'est utilis\u00e9, pour la raison indiqu\u00e9e ci-dessus. Lorsque nous indexons les colonnes avec des cl\u00e9s primaires, la diff\u00e9rence dispara\u00eet presque, mais JSONB reste 1,3 fois plus rapide que EAV. Notez que l'index de la colonne JSONB n'a ici aucun impact, car nous n'utilisons pas la colonne des propri\u00e9t\u00e9s dans les crit\u00e8res d'\u00e9valuation. <\/p>\n<p>Pour la s\u00e9lection de donn\u00e9es bas\u00e9e sur la valeur d'une propri\u00e9t\u00e9, nous obtenons les r\u00e9sultats suivants (\u00e9chelle standard) :<\/p>\n<p><img decoding=\"async\" alt=\"Remplacement de EAV par JSONB dans PostgreSQL\" src=\"\/wp-content\/uploads\/2019\/11\/e9a1fd797ef60132e661da686f6214a3.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nOn peut constater que JSONB est \u00e0 nouveau plus rapide que EAV sans index, mais lorsque EAV est index\u00e9, il fonctionne tout de m\u00eame plus rapidement que JSONB. Cependant, j'ai remarqu\u00e9 que le temps pour les requ\u00eates JSONB \u00e9tait constant, ce qui m'a amen\u00e9 \u00e0 penser que l'index GIN ne fonctionnait pas. En effet, lorsque vous utilisez un index GIN pour une colonne avec des propri\u00e9t\u00e9s remplies, il n'agit que lors de l'utilisation de l'op\u00e9rateur d'inclusion @&gt; . J'ai utilis\u00e9 cela dans un nouveau test, ce qui a eu un \u00e9norme impact sur le temps : seulement 0,153 ms ! C'est 15000 fois plus rapide que EAV et 25000 fois plus rapide que l'op\u00e9rateur -&gt;. <\/p>\n<p>Je pense que c'\u00e9tait suffisamment rapide !<\/p>\n<h3>Taille des tables BD<\/h3>\n<p>\nComparons les tailles des tables selon les deux approches. Dans psql, nous pouvons afficher la taille de toutes les tables et indexes avec la commande <b>dti+<\/b><\/p>\n<p><img decoding=\"async\" alt=\"Remplacement de EAV par JSONB dans PostgreSQL\" src=\"\/wp-content\/uploads\/2019\/11\/c6c1fe7901fe9ae2bd446cf4ae99b923.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPour l'approche EAV, la taille des tables est d'environ 3068 Mo, et celle des index jusqu'\u00e0 3427 Mo, ce qui donne un total de 6,43 Go. Avec l'approche JSONB, il utilise 1817 Mo pour la table et 318 Mo pour les index, soit 2,08 Go. Cela repr\u00e9sente trois fois moins ! Ce fait m'a un peu surpris, car nous stockons les noms des propri\u00e9t\u00e9s dans chaque objet JSONB. <\/p>\n<p>Mais les chiffres parlent d'eux-m\u00eames : dans EAV, nous stockons 2 cl\u00e9s \u00e9trang\u00e8res enti\u00e8res pour la valeur de l'attribut, ce qui nous donne 8 octets de donn\u00e9es suppl\u00e9mentaires. De plus, dans EAV, toutes les valeurs des propri\u00e9t\u00e9s sont stock\u00e9es sous forme de texte, tandis que JSONB utilisera des valeurs num\u00e9riques et logiques \u00e0 l'int\u00e9rieur, lorsque cela est possible, ce qui entra\u00eene un volume d'informations plus faible.<\/p>\n<h3>R\u00e9sultats<\/h3>\n<p>\nDans l'ensemble, je pense que le stockage des propri\u00e9t\u00e9s des entit\u00e9s au format JSONB peut consid\u00e9rablement simplifier la conception et la maintenance de votre base de donn\u00e9es. Si vous effectuez de nombreuses requ\u00eates, tout ce qui est stock\u00e9 dans une table avec l'entit\u00e9 fonctionnera r\u00e9ellement de mani\u00e8re plus efficace. Et le fait que cela facilite l'interaction entre les donn\u00e9es est d\u00e9j\u00e0 un avantage, mais la base de donn\u00e9es r\u00e9sultante est \u00e9galement trois fois plus petite en volume.<\/p>\n<p>De plus, d'apr\u00e8s les tests r\u00e9alis\u00e9s, il est possible de conclure que les pertes de performance sont tr\u00e8s peu significatives. Dans certains cas, JSONB fonctionne m\u00eame plus rapidement que EAV, ce qui le rend encore meilleur. Cependant, ce test de r\u00e9f\u00e9rence ne couvre bien s\u00fbr pas tous les aspects (par exemple, des entit\u00e9s avec un tr\u00e8s grand nombre de propri\u00e9t\u00e9s, un nombre consid\u00e9rable d'augmentations des propri\u00e9t\u00e9s des donn\u00e9es existantes,...). Donc, si vous avez des suggestions pour l'am\u00e9liorer, n'h\u00e9sitez pas \u00e0 les laisser dans les commentaires !<br \/>\n<br \/>Source : <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.2 - 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\/fr\/blog\/administrirovanie\/zamena-eav-na-jsonb-v-postgresql\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"fr_FR\" \/>\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\/fr\/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\udd47Remplacement de EAV par JSONB dans PostgreSQL | ProHoster","description":"TL; DR : JSONB peut consid\u00e9rablement faciliter le d\u00e9veloppement de sch\u00e9mas de bases de donn\u00e9es sans nuire \u00e0 la performance des requ\u00eates. Introduction Pr\u00e9sentons un exemple classique, probablement l'un des plus anciens.","canonical_url":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/zamena-eav-na-jsonb-v-postgresql","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"fr_FR","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\/fr\/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\/fr\/wp-json\/wp\/v2\/posts\/52584","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/comments?post=52584"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts\/52584\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/media?parent=52584"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/categories?post=52584"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/tags?post=52584"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}