{
  "version": "https://jsonfeed.org/version/1.1",
  "title": "Data Bene - Tag: 'Planete PostgreSQL'",
  "language": "fr",
  "home_page_url": "https://www.data-bene.io/fr/",
  "feed_url": "https://www.data-bene.io/fr/blog/tag/planete-postgresql/feed.json",
  "description": "Base de données relationnelles, open-source et adaptives.",
  "items": [{
      "id": "https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe-part-1/",
      "url": "https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe-part-1/",
      "title": "PostgreSQL comme base de données graphique, partie 1: SQL/PGQ dans PostgreSQL",
      "content_html": "\n<html><head></head><body><p><em>Cet article est le deuxième d’une série consacrée aux bases de données graphiques et à PostgreSQL. <a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe/\">Le premier</a> a posé les bases: qu’est-ce qu’un graphe, ce qu’on peut modéliser comme graphe, et le paysage des systèmes graphiques. Celui-ci passe du général au spécifique: comment on interroge les graphes, pourquoi SQL peut être maladroit pour cela, et ce que SQL/PGQ change. Il s’achève sur l’implémentation PostgreSQL, les raisons de son annulation, et quelques notes sur les fonctionnalités principales encore à venir.</em></p><h2 id=\"les-langages-dinterrogation-des-graphes\"><a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe-part-1/#les-langages-dinterrogation-des-graphes\" class=\"heading-anchor\">Les langages d’interrogation des graphes</a></h2><p>Dans <a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe/\">l’article précédent</a>, nous avons terminé par l’observation que les bases de données graphiques existent sous de nombreuses formes, qu’elles diffèrent dans leur façon de stocker les graphes et les modèles de données supportés. Elles diffèrent aussi sur la manière de les interroger.</p><p>Contrairement au monde relationnel, qui s’est convergé précocement vers SQL et l’a conservé comme standard dominant pendant des décennies, l’écosystème des graphes a engendré une prolifération de langages:</p><ul class=\"list\"><li>Cypher<sup class=\"footnote-ref\"><a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe-part-1/#fn1\" id=\"fnref1\">[1]</a></sup>, créé chez Neo4j, représente les motifs en ASCII art:<br><code>(a:Person)-[:KNOWS]-&gt;(b:Person)</code> ;</li><li>Gremlin<sup class=\"footnote-ref\"><a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe-part-1/#fn2\" id=\"fnref2\">[2]</a></sup>, issu d’Apache TinkerPop, est impératif et basé sur des étapes:<br><code>g.V().hasLabel('Person').out('KNOWS')</code> ;</li><li>PGQL<sup class=\"footnote-ref\"><a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe-part-1/#fn3\" id=\"fnref3\">[3]</a></sup>, d’Oracle, intègre les motifs de graphe dans une enveloppe de type SQL ;</li><li>Et en 2024, GQL<sup class=\"footnote-ref\"><a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe-part-1/#fn4\" id=\"fnref4\">[4]</a></sup> a été ratifié comme norme ISO/IEC 39075, le premier nouveau langage de requête de base de données à atteindre une standardisation ISO depuis SQL lui-même.</li></ul><p>Pour cette série, le plus pertinent est SQL/PGQ<sup class=\"footnote-ref\"><a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe-part-1/#fn5\" id=\"fnref5\">[5]</a></sup>, <strong>standardisé dans SQL:2023</strong>. C’est une extension de SQL qui permet de définir des graphes à propriétés sur des tables existantes et de les interroger avec une syntaxe de motifs de type GQL/PGQL intégrée dans un <code>SELECT</code> standard.</p><h2 id=\"a-quel-point-sql-est-il-bon-pour-les-graphes\"><a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe-part-1/#a-quel-point-sql-est-il-bon-pour-les-graphes\" class=\"heading-anchor\">À quel point SQL est-il bon pour les graphes ?</a></h2><p>Prenons un réseau social stocké dans deux tables: <code>person</code> et <code>knows</code>.<br>Une requête Cypher qui cherche les amis d’amis ressemble à:</p><pre class=\"language-cypher\"><code class=\"language-cypher\"> <span class=\"token keyword\">MATCH</span> <span class=\"token punctuation\">(</span>a<span class=\"token operator\">:</span><span class=\"token class-name\">Person</span><span class=\"token punctuation\">)</span><span class=\"token operator\">-</span><span class=\"token punctuation\">[</span><span class=\"token operator\">:</span><span class=\"token relationship property\">KNOWS</span><span class=\"token punctuation\">]</span><span class=\"token operator\">-&gt;</span><span class=\"token punctuation\">(</span>b<span class=\"token punctuation\">)</span><span class=\"token operator\">-</span><span class=\"token punctuation\">[</span><span class=\"token operator\">:</span><span class=\"token relationship property\">KNOWS</span><span class=\"token punctuation\">]</span><span class=\"token operator\">-&gt;</span><span class=\"token punctuation\">(</span>c<span class=\"token punctuation\">)</span>\n <span class=\"token keyword\">WHERE</span> a<span class=\"token punctuation\">.</span>name <span class=\"token operator\">=</span> <span class=\"token string\">'Alice'</span>\n<span class=\"token keyword\">RETURN</span> c<span class=\"token punctuation\">.</span>name</code></pre><p>L’équivalent en SQL pur est une double jointure croisée:</p><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token keyword\">SELECT</span> <span class=\"token keyword\">DISTINCT</span> c<span class=\"token punctuation\">.</span>name\n  <span class=\"token keyword\">FROM</span> person a\n  <span class=\"token keyword\">JOIN</span> knows k1 <span class=\"token keyword\">ON</span> k1<span class=\"token punctuation\">.</span>src <span class=\"token operator\">=</span> a<span class=\"token punctuation\">.</span>id\n  <span class=\"token keyword\">JOIN</span> person b <span class=\"token keyword\">ON</span> k1<span class=\"token punctuation\">.</span>dst <span class=\"token operator\">=</span> b<span class=\"token punctuation\">.</span>id\n  <span class=\"token keyword\">JOIN</span> knows k2 <span class=\"token keyword\">ON</span> k2<span class=\"token punctuation\">.</span>src <span class=\"token operator\">=</span> b<span class=\"token punctuation\">.</span>id\n  <span class=\"token keyword\">JOIN</span> person c <span class=\"token keyword\">ON</span> k2<span class=\"token punctuation\">.</span>dst <span class=\"token operator\">=</span> c<span class=\"token punctuation\">.</span>id\n <span class=\"token keyword\">WHERE</span> a<span class=\"token punctuation\">.</span>name <span class=\"token operator\">=</span> <span class=\"token string\">'Alice'</span><span class=\"token punctuation\">;</span></code></pre><p>Ce n’est pas mal. C’est verbeux, mais c’est expressible, le JOIN est explicite, et que ce soient deux sauts ou dix, chaque saut est conciste à écrire d’avantage de JOINs.</p><p>Essayons quelque chose de plus centré sur les graphes maintenant. Supposons que nous voulons toutes les personnes atteignables depuis Alice en cinq sauts <code>KNOWS</code>. En SQL/PGQ (très similaire à Cypher), c’est un seul motif:</p><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token keyword\">SELECT</span> c<span class=\"token punctuation\">.</span>name\n  <span class=\"token keyword\">FROM</span> GRAPH_TABLE<span class=\"token punctuation\">(</span>\n          social_graph\n    <span class=\"token keyword\">MATCH</span> <span class=\"token punctuation\">(</span>a <span class=\"token operator\">IS</span> Person <span class=\"token keyword\">WHERE</span> a<span class=\"token punctuation\">.</span>name <span class=\"token operator\">=</span> <span class=\"token string\">'Alice'</span><span class=\"token punctuation\">)</span><span class=\"token operator\">-</span><span class=\"token punctuation\">[</span><span class=\"token operator\">IS</span> KNOWS<span class=\"token punctuation\">]</span><span class=\"token operator\">-</span><span class=\"token operator\">&gt;</span>{<span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">5</span>}<span class=\"token punctuation\">(</span>c <span class=\"token operator\">IS</span> Person<span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">COLUMNS</span> <span class=\"token punctuation\">(</span>c<span class=\"token punctuation\">.</span>name<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">)</span> <span class=\"token keyword\">AS</span> g<span class=\"token punctuation\">;</span></code></pre><p>En SQL, cela devient un peu lourd:</p><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token keyword\">WITH</span> RECURSIVE reachable<span class=\"token punctuation\">(</span>id<span class=\"token punctuation\">,</span> depth<span class=\"token punctuation\">,</span> path<span class=\"token punctuation\">)</span> <span class=\"token keyword\">AS</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token keyword\">SELECT</span> p<span class=\"token punctuation\">.</span>id\n         <span class=\"token punctuation\">,</span> <span class=\"token number\">0</span>\n         <span class=\"token punctuation\">,</span> ARRAY<span class=\"token punctuation\">[</span>p<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">]</span>\n      <span class=\"token keyword\">FROM</span> person p\n     <span class=\"token keyword\">WHERE</span> p<span class=\"token punctuation\">.</span>name <span class=\"token operator\">=</span> <span class=\"token string\">'Alice'</span>\n    <span class=\"token keyword\">UNION</span> <span class=\"token keyword\">ALL</span>\n    <span class=\"token keyword\">SELECT</span> k<span class=\"token punctuation\">.</span>dst\n         <span class=\"token punctuation\">,</span> r<span class=\"token punctuation\">.</span>depth <span class=\"token operator\">+</span> <span class=\"token number\">1</span>\n         <span class=\"token punctuation\">,</span> r<span class=\"token punctuation\">.</span>path <span class=\"token operator\">||</span> k<span class=\"token punctuation\">.</span>dst\n      <span class=\"token keyword\">FROM</span> reachable r\n      <span class=\"token keyword\">JOIN</span> knows k <span class=\"token keyword\">ON</span> k<span class=\"token punctuation\">.</span>src <span class=\"token operator\">=</span> r<span class=\"token punctuation\">.</span>id\n     <span class=\"token keyword\">WHERE</span> r<span class=\"token punctuation\">.</span>depth <span class=\"token operator\">&lt;</span> <span class=\"token number\">5</span>\n       <span class=\"token operator\">AND</span> k<span class=\"token punctuation\">.</span>dst <span class=\"token operator\">&lt;&gt;</span> <span class=\"token keyword\">ALL</span><span class=\"token punctuation\">(</span>r<span class=\"token punctuation\">.</span>path<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">SELECT</span> <span class=\"token keyword\">DISTINCT</span> p<span class=\"token punctuation\">.</span>name\n  <span class=\"token keyword\">FROM</span> reachable r\n  <span class=\"token keyword\">JOIN</span> person p <span class=\"token keyword\">ON</span> p<span class=\"token punctuation\">.</span>id <span class=\"token operator\">=</span> r<span class=\"token punctuation\">.</span>id\n <span class=\"token keyword\">WHERE</span> r<span class=\"token punctuation\">.</span>depth <span class=\"token operator\">&gt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></code></pre><p>L’auteur encode désormais la limite de profondeur, transporte le chemin dans un tableau pour éviter les cycles, et retire la ligne racine à la fin. PostgreSQL 14 a ajouté les clauses <code>SEARCH</code> et <code>CYCLE</code><sup class=\"footnote-ref\"><a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe-part-1/#fn6\" id=\"fnref6\">[6]</a></sup> qui masquent une partie de cette gestion administrative, mais la requête reste un calcul de point fixe récursif qui arrive à produire le bon résultat.</p><p>Bien que ce soit un parcours de graphe basique, les choses deviennent encore plus complexes. Pour les plus courts chemins, il faudrait suivre la distance et faire du “pruning”. Si on demande un tracé (pas de répétition d’arêtes), il faudrait suivre les arêtes, pas seulement les sommets.</p><h2 id=\"definir-et-interroger-un-graphe-en-sql/pgq\"><a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe-part-1/#definir-et-interroger-un-graphe-en-sql/pgq\" class=\"heading-anchor\">Définir et interroger un graphe en SQL/PGQ</a></h2><p>À partir d’ici, nous utilisons un exemple plus riche, situé dans la galaxie Star Wars. Les Jedi combattaient sur des planètes, et les Sith sur des stations. Les tables de sommets sont <code>jedi</code>, <code>sith</code>, <code>planet</code> et <code>station</code>, chacune avec un <code>id</code> et un <code>name</code>, plus un <code>title</code> pour les combattants et une <code>region</code> pour les lieux. Deux tables d’arêtes, <code>fought_on_planet</code> et <code>fought_on_station</code>, contiennent chacune un identifiant source, un identifiant destination, et le nom de la bataille.</p><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token keyword\">CREATE</span> <span class=\"token keyword\">TABLE</span> jedi <span class=\"token punctuation\">(</span>\n    id     <span class=\"token keyword\">BIGINT</span> <span class=\"token keyword\">PRIMARY</span> <span class=\"token keyword\">KEY</span><span class=\"token punctuation\">,</span>\n    name   <span class=\"token keyword\">TEXT</span><span class=\"token punctuation\">,</span>\n    title  <span class=\"token keyword\">TEXT</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">CREATE</span> <span class=\"token keyword\">TABLE</span> sith <span class=\"token punctuation\">(</span>\n    id     <span class=\"token keyword\">BIGINT</span> <span class=\"token keyword\">PRIMARY</span> <span class=\"token keyword\">KEY</span><span class=\"token punctuation\">,</span>\n    name   <span class=\"token keyword\">TEXT</span><span class=\"token punctuation\">,</span>\n    title  <span class=\"token keyword\">TEXT</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">CREATE</span> <span class=\"token keyword\">TABLE</span> planet <span class=\"token punctuation\">(</span>\n    id      <span class=\"token keyword\">BIGINT</span> <span class=\"token keyword\">PRIMARY</span> <span class=\"token keyword\">KEY</span><span class=\"token punctuation\">,</span>\n    name    <span class=\"token keyword\">TEXT</span><span class=\"token punctuation\">,</span>\n    region  <span class=\"token keyword\">TEXT</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">CREATE</span> <span class=\"token keyword\">TABLE</span> station <span class=\"token punctuation\">(</span>\n    id      <span class=\"token keyword\">BIGINT</span> <span class=\"token keyword\">PRIMARY</span> <span class=\"token keyword\">KEY</span><span class=\"token punctuation\">,</span>\n    name    <span class=\"token keyword\">TEXT</span><span class=\"token punctuation\">,</span>\n    region  <span class=\"token keyword\">TEXT</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">CREATE</span> <span class=\"token keyword\">TABLE</span> fought_on_planet <span class=\"token punctuation\">(</span>\n    a       <span class=\"token keyword\">BIGINT</span> <span class=\"token keyword\">REFERENCES</span> jedi <span class=\"token punctuation\">(</span>id<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    b       <span class=\"token keyword\">BIGINT</span> <span class=\"token keyword\">REFERENCES</span> planet <span class=\"token punctuation\">(</span>id<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    battle  <span class=\"token keyword\">TEXT</span><span class=\"token punctuation\">,</span>\n    <span class=\"token keyword\">PRIMARY</span> <span class=\"token keyword\">KEY</span> <span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">,</span> b<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">CREATE</span> <span class=\"token keyword\">TABLE</span> fought_on_station <span class=\"token punctuation\">(</span>\n    a       <span class=\"token keyword\">BIGINT</span> <span class=\"token keyword\">REFERENCES</span> sith <span class=\"token punctuation\">(</span>id<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    b       <span class=\"token keyword\">BIGINT</span> <span class=\"token keyword\">REFERENCES</span> station <span class=\"token punctuation\">(</span>id<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    battle  <span class=\"token keyword\">TEXT</span><span class=\"token punctuation\">,</span>\n    <span class=\"token keyword\">PRIMARY</span> <span class=\"token keyword\">KEY</span> <span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">,</span> b<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre><p>Le graphe est déclaré sur celles-ci:</p><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token keyword\">CREATE</span> PROPERTY GRAPH galaxy\n    VERTEX <span class=\"token keyword\">TABLES</span> <span class=\"token punctuation\">(</span>\n        jedi    <span class=\"token keyword\">KEY</span> <span class=\"token punctuation\">(</span>id<span class=\"token punctuation\">)</span> LABEL force_user PROPERTIES <span class=\"token punctuation\">(</span>id<span class=\"token punctuation\">,</span> name<span class=\"token punctuation\">,</span> title<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        sith    <span class=\"token keyword\">KEY</span> <span class=\"token punctuation\">(</span>id<span class=\"token punctuation\">)</span> LABEL force_user PROPERTIES <span class=\"token punctuation\">(</span>id<span class=\"token punctuation\">,</span> name<span class=\"token punctuation\">,</span> title<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        planet  <span class=\"token keyword\">KEY</span> <span class=\"token punctuation\">(</span>id<span class=\"token punctuation\">)</span> LABEL place      PROPERTIES <span class=\"token punctuation\">(</span>id<span class=\"token punctuation\">,</span> name<span class=\"token punctuation\">,</span> region<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        station <span class=\"token keyword\">KEY</span> <span class=\"token punctuation\">(</span>id<span class=\"token punctuation\">)</span> LABEL place      PROPERTIES <span class=\"token punctuation\">(</span>id<span class=\"token punctuation\">,</span> name<span class=\"token punctuation\">,</span> region<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">)</span>\n    EDGE <span class=\"token keyword\">TABLES</span> <span class=\"token punctuation\">(</span>\n        fought_on_planet\n            SOURCE <span class=\"token keyword\">KEY</span> <span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">)</span>      <span class=\"token keyword\">REFERENCES</span> jedi <span class=\"token punctuation\">(</span>id<span class=\"token punctuation\">)</span>\n            DESTINATION <span class=\"token keyword\">KEY</span> <span class=\"token punctuation\">(</span>b<span class=\"token punctuation\">)</span> <span class=\"token keyword\">REFERENCES</span> planet <span class=\"token punctuation\">(</span>id<span class=\"token punctuation\">)</span>\n            LABEL fought_at     PROPERTIES <span class=\"token punctuation\">(</span>battle<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        fought_on_station\n            SOURCE <span class=\"token keyword\">KEY</span> <span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">)</span>      <span class=\"token keyword\">REFERENCES</span> sith <span class=\"token punctuation\">(</span>id<span class=\"token punctuation\">)</span>\n            DESTINATION <span class=\"token keyword\">KEY</span> <span class=\"token punctuation\">(</span>b<span class=\"token punctuation\">)</span> <span class=\"token keyword\">REFERENCES</span> station <span class=\"token punctuation\">(</span>id<span class=\"token punctuation\">)</span>\n            LABEL fought_at     PROPERTIES <span class=\"token punctuation\">(</span>battle<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre><p>Les labels regroupent des tables: <code>force_user</code> couvre deux tables de sommets, <code>place</code> en couvre deux, et <code>fought_at</code> couvre les deux tables d’arêtes. Le graphe ne contient aucune donnée.<br>Dans PostgreSQL, c’est un nouveau type de relation (<code>RELKIND_PROPGRAPH</code>) qui vit dans <code>pg_class</code> sans “heap” (table) et sans colonne propre, ce qui fait qu’il se comporte comme une vue. Cinq nouveaux catalogues (<code>pg_propgraph_element</code>, <code>pg_propgraph_label</code> et trois autres) enregistrent ses éléments, labels et propriétés.</p><p>L’interroger:</p><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token keyword\">SELECT</span> <span class=\"token operator\">*</span>\n<span class=\"token keyword\">FROM</span> GRAPH_TABLE <span class=\"token punctuation\">(</span>\n            galaxy\n      <span class=\"token keyword\">MATCH</span> <span class=\"token punctuation\">(</span>a <span class=\"token operator\">IS</span> force_user<span class=\"token punctuation\">)</span><span class=\"token operator\">-</span><span class=\"token punctuation\">[</span><span class=\"token operator\">IS</span> fought_at<span class=\"token punctuation\">]</span><span class=\"token operator\">-</span><span class=\"token operator\">&gt;</span><span class=\"token punctuation\">(</span>b <span class=\"token operator\">IS</span> place<span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">COLUMNS</span> <span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">.</span>name <span class=\"token keyword\">AS</span> fighter<span class=\"token punctuation\">,</span> b<span class=\"token punctuation\">.</span>name <span class=\"token keyword\">AS</span> battlefield<span class=\"token punctuation\">,</span> b<span class=\"token punctuation\">.</span>region<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre><h3 id=\"comment-fonctionne-la-reecriture\"><a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe-part-1/#comment-fonctionne-la-reecriture\" class=\"heading-anchor\">Comment fonctionne la réécriture ?</a></h3><p>PostgreSQL n’a pas de nouveau nœud “exécuteur”. L’analyseur transforme <code>GRAPH_TABLE</code> en un nouveau type de “range-table”, <code>RTE_GRAPH_TABLE</code>. La réécriture, le même stade qui étend les vues, la remplace ensuite par une sous-requête ordinaire.<br>Il procède en quatre étapes:</p><ol class=\"list\"><li>Le motif est lu de gauche à droite dans une liste de motifs d’éléments: sommets, arêtes dans les deux sens, et sous-motifs imbriqués.</li><li>Chaque nom de variable unique devient un facteur de chemin. Une variable qui apparaît deux fois, dans un cycle qui retourne à <code>a</code>, partage un même facteur, et ses prédicats sont conjoints par <code>AND</code>.</li><li>Chaque expression de label est résolue vers les tables qu’elle couvre, donnant un élément de chemin par table.</li><li>Chaque combinaison d’éléments le long du chemin est énumérée par un DFS (recherche en profondeur d’abord) récursif. Une combinaison n’est valide que si les clés source et destination de chaque table d’arêtes relient vraiment les deux tables de sommets voisines. Chaque combinaison valide devient un <code>JOIN</code> entre les tables d’arêtes et de sommets sur ces clés, et toutes sont combinées par <code>UNION ALL</code>.</li></ol><p>Dans notre requête, <code>force_user</code> a deux tables, <code>fought_at</code> en a deux, et <code>place</code> en a deux, il y a donc 2 × 2 × 2 = 8 combinaisons. Seulement deux sont valides: un Jedi sur une planète, et un Sith dans une station. La requête devient équivalente à:</p><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token keyword\">SELECT</span> jedi<span class=\"token punctuation\">.</span>name<span class=\"token punctuation\">,</span> planet<span class=\"token punctuation\">.</span>name<span class=\"token punctuation\">,</span> planet<span class=\"token punctuation\">.</span>region\n  <span class=\"token keyword\">FROM</span> jedi<span class=\"token punctuation\">,</span> fought_on_planet<span class=\"token punctuation\">,</span> planet\n <span class=\"token keyword\">WHERE</span> jedi<span class=\"token punctuation\">.</span>id <span class=\"token operator\">=</span> fought_on_planet<span class=\"token punctuation\">.</span>a\n   <span class=\"token operator\">AND</span> planet<span class=\"token punctuation\">.</span>id <span class=\"token operator\">=</span> fought_on_planet<span class=\"token punctuation\">.</span>b\n<span class=\"token keyword\">UNION</span> <span class=\"token keyword\">ALL</span>\n<span class=\"token keyword\">SELECT</span> sith<span class=\"token punctuation\">.</span>name<span class=\"token punctuation\">,</span> station<span class=\"token punctuation\">.</span>name<span class=\"token punctuation\">,</span> station<span class=\"token punctuation\">.</span>region\n  <span class=\"token keyword\">FROM</span> sith<span class=\"token punctuation\">,</span> fought_on_station<span class=\"token punctuation\">,</span> station\n <span class=\"token keyword\">WHERE</span> sith<span class=\"token punctuation\">.</span>id <span class=\"token operator\">=</span> fought_on_station<span class=\"token punctuation\">.</span>a\n   <span class=\"token operator\">AND</span> station<span class=\"token punctuation\">.</span>id <span class=\"token operator\">=</span> fought_on_station<span class=\"token punctuation\">.</span>b<span class=\"token punctuation\">;</span></code></pre><p>À partir de ce point, le planificateur et l’exécuteur voient des jointures et une union, rien de spécifique aux graphes. Ceci a une certaine valeur car nous bénéficions des index, des statistiques, de l’interrogation parallèle et de tout ce que PostgreSQL possède — ce qui rappelle l’argument que nous faisons dans le <a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe/\">précédent article</a> de la série sur les bases de données graphes construites sur des systèmes matures.</p><p><strong>Il y a ici une subtilité qui compte pour la lecture de tout benchmark comparant les deux formalismes.</strong></p><p>Dans un motif de longueur fixe, SQL/PGQ est obligé de toucher les tables de sommets. Le motif lie les sommets, donc la jointure vers la table de sommets fait partie de la sémantique même lorsqu’aucune propriété de sommet n’est demandée, car il n’y a pas de clés étrangères (FK). Si vous modélisiez le même graphe vous-même en SQL pur et aviez seulement besoin de la traversée des arêtes, à condition d’avoir défini des FK, joindre les tables d’arêtes seules suffit.</p><p><em>Note: il y a un effort récent, non validé, de la part de hackers PostgreSQL pour éliminer les inner joins basés sur les clés étrangères, ce qui serait bénéfique pour la réécriture SQL/PGQ + FK sur les tables élémentaires du graphe<sup class=\"footnote-ref\"><a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe-part-1/#fn7\" id=\"fnref7\">[7]</a></sup>.</em></p><h3 id=\"ce-qui-est-supporte-et-ce-qui-ne-lest-pas\"><a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe-part-1/#ce-qui-est-supporte-et-ce-qui-ne-lest-pas\" class=\"heading-anchor\">Ce qui est supporté et ce qui ne l’est pas</a></h3><p>La norme recense 100 fonctionnalités. L’implémentation validée en couvrait 26. Elle supporte les motifs graphiques avec <code>WHERE</code>, les motifs de sommets, les motifs d’arêtes sous forme complète et abrégée, la disjonction de labels (<code>label1|label2</code>), les références de propriétés, <code>GRAPH_TABLE</code>, le DDL incluant <code>ALTER</code> et <code>DROP</code>, plusieurs labels par table élémentaire, et les vues comme tables élémentaires.</p><p>Les plus intéressantes des 74 manquantes relèvent (pour la plupart) de cinq mécanismes que la norme définit au-dessus d’un motif de base:</p><table><thead><tr><th>Mécanisme</th><th>Ce qu’il décide</th><th>PostgreSQL</th></tr></thead><tbody><tr><td>Quantificateurs: <code>{n,m}</code>, <code>{n}</code>, <code>+</code>, <code>*</code></td><td>Le nombre de sauts couverts par un motif</td><td>Non supporté</td></tr><tr><td></td><td></td><td></td></tr><tr><td>Modes de chemin: <code>WALK</code>, <code>TRAIL</code>, <code>SIMPLE</code>, <code>ACYCLIC</code></td><td>Quels chemins sont admissibles (quoi qui peut se répéter)</td><td>Comporte comme <code>WALK</code>, mots-clés rejetés</td></tr><tr><td></td><td></td><td></td></tr><tr><td>Préfixes de recherche de chemin: <code>ALL</code>, <code>ANY</code>, <code>ALL SHORTEST</code>, <code>SHORTEST n</code></td><td>Quels chemins admissibles sont retournés</td><td>Seulement <code>ALL</code>, le défaut</td></tr><tr><td></td><td></td><td></td></tr><tr><td>Modes de correspondance: <code>REPEATABLE ELEMENTS</code>, <code>DIFFERENT EDGES</code></td><td>Si les arêtes peuvent se lier deux fois</td><td>Seulement <code>REPEATABLE ELEMENTS</code></td></tr><tr><td></td><td></td><td></td></tr><tr><td>Plusieurs motifs de chemin séparés par des virgules dans un <code>MATCH</code></td><td>Jointure de motifs sur des variables partagées</td><td>Patch existant, retardé après les quantificateurs</td></tr></tbody></table><p>PostgreSQL n’est pas seul ici. Le SQL/PGQ d’Oracle est tout aussi réduit, DuckPGQ n’ajoute que <code>ANY SHORTEST</code>, et l’ancien PGQL d’Oracle supporte la plupart de ces fonctionnalités.</p><h3 id=\"lannulation-git-revert\"><a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe-part-1/#lannulation-git-revert\" class=\"heading-anchor\">L’annulation (“git revert”)</a></h3><p>SQL/PGQ a été validé le 16 mars 2026 pour PostgreSQL 19. Début septembre, une discussion sur <code>pgsql-hackers</code> concernant certains problèmes dans sa représentation/catalogue et ses dépendances d’objets s’est achevé par une décision de le retirer.<br>Les reviewers ont estimé qu’il devait être retiré de cette version afin que les problèmes puissent être corrigés proprement pour 20, sans la pression de la compatibilité ascendante.</p><p>La fonctionnalité devrait revenir dans une version future. La réécriture elle-même n’est pas la partie en cours de refonte, elle devrait donc survivre, inchangée, ce qui signifie que le travail supplémentaire — VLE (variable length edge), motifs multi-chemins, etc. — pourra s’appuyer sur le même socle.</p><p>Il est d’ailleurs à noter que tout cela n’a pas à être nécessairement dans le noyau. PostgreSQL n’a pas de parser hook, donc une extension ne peut pas ajouter de grammaire, et les parser hooks ont été proposés et discutés à maintes reprises sans aboutir. La dernière mention concernait la manière de publier SQL/PGQ comme fonctionnalité expérimentale<sup class=\"footnote-ref\"><a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe-part-1/#fn8\" id=\"fnref8\">[8]</a></sup>.<br>Il ne reste à SQL/PGQ que deux options: travailler dans le noyau, ou faire ce que fait Apache AGE et parser une chaîne à l’exécution ; bien sûr, la deuxième est un élément pour une extension, pas pour une fonctionnalité du noyau.<br><strong>Si les extensions avaient pu étendre le parseur, cela aurait pu être construit et prouvé hors de l’arbre, puis ensuite considéré pour un module contrib ou pour le noyau. Ce n’est pas un argument en faveur des parser hooks. C’est une observation sur là où le coût de ne pas les avoir finit par peser.</strong></p><h3 id=\"la-fonctionnalite-que-tout-le-monde-reclame\"><a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe-part-1/#la-fonctionnalite-que-tout-le-monde-reclame\" class=\"heading-anchor\">La fonctionnalité que tout le monde réclame</a></h3><p>Des morceaux manquants, l’un domine chaque conversation sur les requêtes de graphe: <strong>les arêtes de longueur variable</strong> (VLE).<br>C’est la fonctionnalité que les utilisatrices et utilisateurs de graphes réclament en premier, et c’est souvent la raison pour laquelle on se tourne vers un langage de requête de graphe plutôt que d’écrire des jointures. La difficulté est proportionnelle à l’échelle. Un motif borné sur deux ou trois sauts peut être fait avec une réécriture similaire vers des jointures. Un motif pouvant atteindre des centaines de sauts, ou s’exécuter de manière non bornée jusqu’à épuisement du graphe, est un problème différent avec ses propres exigences de mémoire, de terminaison et de gestion des cycles.</p><p>La norme rend cela plus difficile qu’il n’y paraît, car elle définit plusieurs mécanismes et fonctionnalités qui interagissent avec elle. Comment le motif s’étend, quels chemins comptent comme admissibles, et lesquels de ceux-ci sont retournés sont décidés indépendamment, et chaque combinaison implique une stratégie d’exécution différente. Tous les chemins sur une profondeur bornée, un seul chemin le plus court, et les extrémités atteignables distinctes sont des motifs différents dont il faut tenir compte dans la conception. Bien sûr, on NE peut PAS tout supporter, mais il est important de garder ces sémantiques en tête.</p><p>Les implémentations varient. Une approche est une nouvelle réécriture, cette fois vers des CTE récursifs, s’appuyant sur les clauses <code>SEARCH</code> et <code>CYCLE</code> et faisant beaucoup de gestion administrative directement dans la requête pour les différentes sémantiques. En bout de ligne, c’est un BFS (recherche en largeur) basé sur des ensembles exprimé sous forme de jointures ; c’est acceptable mais ce ne sera ni performant ni flexible à combiner avec d’autres fonctionnalités comme les variables de chemin.</p><p>Une autre approche étend chaque longueur possible dans son propre <code>UNION ALL</code>, ce qui ne peut pas gérer le cas non borné. C’est une très mauvaise idée ; Oracle fait ça. Puis il y a les stratégies au niveau de l’exécuteur: DFS avec état de chemin pour le backtracking, ou BFS exécuté directement dans l’exécuteur (tous avec de nouveaux nœuds exécuteur). Chacune est adaptée à un objectif différent, qu’il s’agisse d’accessibilité, de plus court chemin, ou d’énumération de tous les chemins possibles. L’implémentation future prendra en compte toutes celles-ci, <strong>autrement on ne peut pas considérer Postgres dans la course, en aucune manière.</strong></p><h2 id=\"points-cles\"><a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe-part-1/#points-cles\" class=\"heading-anchor\">Points clés</a></h2><p>SQL/PGQ réécrit les motifs de graphe en jointures — pas de nouveaux nœuds exécuteur, pas de moteur de graphe. Le planificateur gère le reste avec les index, les statistiques et l’interrogation parallèle.</p><p>L’implémentation validée couvrait 26 des 100 fonctionnalités de la norme, de quoi prouver l’approche mais en s’arrêtant avant les problèmes difficiles. Les quantificateurs, les modes de chemin et les arêtes de longueur variable étaient intentionnellement différés.</p><p>L’annulation est lié au “timing”. Les catalogues et le suivi des dépendances nécessitent une base plus propre pour PostgreSQL 20. Le moteur de réécriture lui-même n’est pas en cours de refonte.</p><p>La gestion des arêtes de longueur variable est la fonctionnalité requise. La norme définit plusieurs mécanismes au-dessus du VLE qui impliquent différentes stratégies d’exécution — BFS basé sur des ensembles via des CTE récursives, bras <code>UNION ALL</code> par longueur, ou DFS/BFS au niveau de l’exécuteur avec de nouveaux nœuds. Chacune sert un objectif différent.</p><p>Sans parser hooks, SQL/PGQ doit vivre dans le noyau ou utiliser un analyseur de chaîne à l’exécution.</p><h2 id=\"et-maintenant\"><a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe-part-1/#et-maintenant\" class=\"heading-anchor\">Et maintenant ?</a></h2><p>Le prochain article examine les autres options de graphes dans PostgreSQL: Apache AGE, pgRouting, et le cas pratique pour ou contre chacune.<br>Ensuite, un benchmark comparant SQL/PGQ à Apache AGE.<br>Et enfin, à quoi ressemble la vision à long terme pour les requêtes de graphe dans PostgreSQL, et pourquoi la trajectoire pointe vers l’absorption des charges de travail des graphes dans les systèmes relationnels.</p><hr class=\"footnotes-sep\"><section class=\"footnotes\"><ol class=\"footnotes-list\"><li id=\"fn1\" class=\"footnote-item\"><p><a href=\"https://neo4j.com/docs/getting-started/cypher/\" rel=\"noopener\">https://neo4j.com/docs/getting-started/cypher/</a> <a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe-part-1/#fnref1\" class=\"footnote-backref\">↩︎</a></p></li><li id=\"fn2\" class=\"footnote-item\"><p><a href=\"https://tinkerpop.apache.org/gremlin.html\" rel=\"noopener\">https://tinkerpop.apache.org/gremlin.html</a> <a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe-part-1/#fnref2\" class=\"footnote-backref\">↩︎</a></p></li><li id=\"fn3\" class=\"footnote-item\"><p><a href=\"https://pgql-lang.org/\" rel=\"noopener\">https://pgql-lang.org/</a> <a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe-part-1/#fnref3\" class=\"footnote-backref\">↩︎</a></p></li><li id=\"fn4\" class=\"footnote-item\"><p><a href=\"https://www.iso.org/standard/76120.html\" rel=\"noopener\">https://www.iso.org/standard/76120.html</a> <a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe-part-1/#fnref4\" class=\"footnote-backref\">↩︎</a></p></li><li id=\"fn5\" class=\"footnote-item\"><p><a href=\"https://www.iso.org/standard/79473.html\" rel=\"noopener\">https://www.iso.org/standard/79473.html</a> <a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe-part-1/#fnref5\" class=\"footnote-backref\">↩︎</a></p></li><li id=\"fn6\" class=\"footnote-item\"><p><a href=\"https://www.postgresql.org/docs/current/queries-with.html#QUERIES-WITH-SEARCH\" rel=\"noopener\">https://www.postgresql.org/docs/current/queries-with.html#QUERIES-WITH-SEARCH</a> <a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe-part-1/#fnref6\" class=\"footnote-backref\">↩︎</a></p></li><li id=\"fn7\" class=\"footnote-item\"><p><a href=\"https://www.postgresql.org/message-id/CAMbWs49-v9FGX+B=tsCxUq_FPX09ZNvXjj+TaTx0m-MAVmY5TA@mail.gmail.com\" rel=\"noopener\">https://www.postgresql.org/message-id/CAMbWs49-v9FGX+B=tsCxUq_FPX09ZNvXjj+TaTx0m-MAVmY5TA@mail.gmail.com</a> <a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe-part-1/#fnref7\" class=\"footnote-backref\">↩︎</a></p></li><li id=\"fn8\" class=\"footnote-item\"><p><a href=\"https://www.postgresql.org/message-id/33d590a7-4e26-41a8-acd4-51720dddf969%40eisentraut.org\" rel=\"noopener\">https://www.postgresql.org/message-id/33d590a7-4e26-41a8-acd4-51720dddf969%40eisentraut.org</a> <a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe-part-1/#fnref8\" class=\"footnote-backref\">↩︎</a></p></li></ol></section></body></html>\n",
      "date_published": "2026-10-21T00:00:00Z"
    }
    ,{
      "id": "https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe/",
      "url": "https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe/",
      "title": "PostgreSQL comme base de données graphe, partie 0 : introduction, graphes, bases de données graphe",
      "content_html": "\n<html><head><style id=\"MJX-CHTML-styles\">\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmjx-c.mjx-c7B::before {\n  padding: 0.75em 0.5em 0.25em 0;\n  content: \"{\";\n}\n\nmjx-c.mjx-c7D::before {\n  padding: 0.75em 0.5em 0.25em 0;\n  content: \"}\";\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmjx-math {\n  display: inline-block;\n  text-align: left;\n  line-height: 0;\n  text-indent: 0;\n  font-style: normal;\n  font-weight: normal;\n  font-size: 100%;\n  font-size-adjust: none;\n  letter-spacing: normal;\n  border-collapse: collapse;\n  word-wrap: normal;\n  word-spacing: normal;\n  white-space: nowrap;\n  direction: ltr;\n  padding: 1px 0;\n}\n\nmjx-container[jax=\"CHTML\"][display=\"true\"] {\n  display: block;\n  text-align: center;\n  margin: 1em 0;\n}\n\nmjx-container[jax=\"CHTML\"][display=\"true\"][width=\"full\"] {\n  display: flex;\n}\n\nmjx-container[jax=\"CHTML\"][display=\"true\"] mjx-math {\n  padding: 0;\n}\n\nmjx-container[jax=\"CHTML\"][justify=\"left\"] {\n  text-align: left;\n}\n\nmjx-container[jax=\"CHTML\"][justify=\"right\"] {\n  text-align: right;\n}\n\nmjx-mi {\n  display: inline-block;\n  text-align: left;\n}\n\nmjx-c {\n  display: inline-block;\n}\n\nmjx-utext {\n  display: inline-block;\n  padding: .75em 0 .2em 0;\n}\n\nmjx-mo {\n  display: inline-block;\n  text-align: left;\n}\n\nmjx-stretchy-h {\n  display: inline-table;\n  width: 100%;\n}\n\nmjx-stretchy-h > * {\n  display: table-cell;\n  width: 0;\n}\n\nmjx-stretchy-h > * > mjx-c {\n  display: inline-block;\n  transform: scalex(1.0000001);\n}\n\nmjx-stretchy-h > * > mjx-c::before {\n  display: inline-block;\n  width: initial;\n}\n\nmjx-stretchy-h > mjx-ext {\n  /* IE */ overflow: hidden;\n  /* others */ overflow: clip visible;\n  width: 100%;\n}\n\nmjx-stretchy-h > mjx-ext > mjx-c::before {\n  transform: scalex(500);\n}\n\nmjx-stretchy-h > mjx-ext > mjx-c {\n  width: 0;\n}\n\nmjx-stretchy-h > mjx-beg > mjx-c {\n  margin-right: -.1em;\n}\n\nmjx-stretchy-h > mjx-end > mjx-c {\n  margin-left: -.1em;\n}\n\nmjx-stretchy-v {\n  display: inline-block;\n}\n\nmjx-stretchy-v > * {\n  display: block;\n}\n\nmjx-stretchy-v > mjx-beg {\n  height: 0;\n}\n\nmjx-stretchy-v > mjx-end > mjx-c {\n  display: block;\n}\n\nmjx-stretchy-v > * > mjx-c {\n  transform: scaley(1.0000001);\n  transform-origin: left center;\n  overflow: hidden;\n}\n\nmjx-stretchy-v > mjx-ext {\n  display: block;\n  height: 100%;\n  box-sizing: border-box;\n  border: 0px solid transparent;\n  /* IE */ overflow: hidden;\n  /* others */ overflow: visible clip;\n}\n\nmjx-stretchy-v > mjx-ext > mjx-c::before {\n  width: initial;\n  box-sizing: border-box;\n}\n\nmjx-stretchy-v > mjx-ext > mjx-c {\n  transform: scaleY(500) translateY(.075em);\n  overflow: visible;\n}\n\nmjx-mark {\n  display: inline-block;\n  height: 0px;\n}\n\nmjx-TeXAtom {\n  display: inline-block;\n  text-align: left;\n}\n\nmjx-c.mjx-c1D43A.TEX-I::before {\n  padding: 0.705em 0.786em 0.022em 0;\n  content: \"G\";\n}\n\nmjx-c.mjx-c28::before {\n  padding: 0.75em 0.389em 0.25em 0;\n  content: \"(\";\n}\n\nmjx-c.mjx-c1D449.TEX-I::before {\n  padding: 0.683em 0.769em 0.022em 0;\n  content: \"V\";\n}\n\nmjx-c.mjx-c2C::before {\n  padding: 0.121em 0.278em 0.194em 0;\n  content: \",\";\n}\n\nmjx-c.mjx-c1D438.TEX-I::before {\n  padding: 0.68em 0.764em 0 0;\n  content: \"E\";\n}\n\nmjx-c.mjx-c29::before {\n  padding: 0.75em 0.389em 0.25em 0;\n  content: \")\";\n}\n\nmjx-c.mjx-c1D452.TEX-I::before {\n  padding: 0.442em 0.466em 0.011em 0;\n  content: \"e\";\n}\n\nmjx-c.mjx-c2286::before {\n  padding: 0.636em 0.778em 0.138em 0;\n  content: \"\\2286\";\n}\n\nmjx-c.mjx-cD7::before {\n  padding: 0.491em 0.778em 0 0;\n  content: \"\\D7\";\n}\n\nmjx-c.mjx-c1D462.TEX-I::before {\n  padding: 0.442em 0.572em 0.011em 0;\n  content: \"u\";\n}\n\nmjx-c.mjx-c1D463.TEX-I::before {\n  padding: 0.443em 0.485em 0.011em 0;\n  content: \"v\";\n}\n\nmjx-c.mjx-c3D::before {\n  padding: 0.583em 0.778em 0.082em 0;\n  content: \"=\";\n}\n\nmjx-c.mjx-c2208::before {\n  padding: 0.54em 0.667em 0.04em 0;\n  content: \"\\2208\";\n}\n\nmjx-c.mjx-c1D464.TEX-I::before {\n  padding: 0.443em 0.716em 0.011em 0;\n  content: \"w\";\n}\n\nmjx-c.mjx-c3A::before {\n  padding: 0.43em 0.278em 0 0;\n  content: \":\";\n}\n\nmjx-c.mjx-c2192::before {\n  padding: 0.511em 1em 0.011em 0;\n  content: \"\\2192\";\n}\n\nmjx-c.mjx-c211D.TEX-A::before {\n  padding: 0.683em 0.722em 0 0;\n  content: \"R\";\n}\n\nmjx-c.mjx-c1D460.TEX-I::before {\n  padding: 0.442em 0.469em 0.01em 0;\n  content: \"s\";\n}\n\nmjx-c.mjx-c1D45D.TEX-I::before {\n  padding: 0.442em 0.503em 0.194em 0;\n  content: \"p\";\n}\n\nmjx-c.mjx-c1D45C.TEX-I::before {\n  padding: 0.441em 0.485em 0.011em 0;\n  content: \"o\";\n}\n\n\nmjx-container[jax=\"CHTML\"] {\n  line-height: 0;\n}\n\nmjx-container [space=\"1\"] {\n  margin-left: .111em;\n}\n\nmjx-container [space=\"2\"] {\n  margin-left: .167em;\n}\n\nmjx-container [space=\"3\"] {\n  margin-left: .222em;\n}\n\nmjx-container [space=\"4\"] {\n  margin-left: .278em;\n}\n\nmjx-container [space=\"5\"] {\n  margin-left: .333em;\n}\n\nmjx-container [rspace=\"1\"] {\n  margin-right: .111em;\n}\n\nmjx-container [rspace=\"2\"] {\n  margin-right: .167em;\n}\n\nmjx-container [rspace=\"3\"] {\n  margin-right: .222em;\n}\n\nmjx-container [rspace=\"4\"] {\n  margin-right: .278em;\n}\n\nmjx-container [rspace=\"5\"] {\n  margin-right: .333em;\n}\n\nmjx-container [size=\"s\"] {\n  font-size: 70.7%;\n}\n\nmjx-container [size=\"ss\"] {\n  font-size: 50%;\n}\n\nmjx-container [size=\"Tn\"] {\n  font-size: 60%;\n}\n\nmjx-container [size=\"sm\"] {\n  font-size: 85%;\n}\n\nmjx-container [size=\"lg\"] {\n  font-size: 120%;\n}\n\nmjx-container [size=\"Lg\"] {\n  font-size: 144%;\n}\n\nmjx-container [size=\"LG\"] {\n  font-size: 173%;\n}\n\nmjx-container [size=\"hg\"] {\n  font-size: 207%;\n}\n\nmjx-container [size=\"HG\"] {\n  font-size: 249%;\n}\n\nmjx-container [width=\"full\"] {\n  width: 100%;\n}\n\nmjx-box {\n  display: inline-block;\n}\n\nmjx-block {\n  display: block;\n}\n\nmjx-itable {\n  display: inline-table;\n}\n\nmjx-row {\n  display: table-row;\n}\n\nmjx-row > * {\n  display: table-cell;\n}\n\nmjx-mtext {\n  display: inline-block;\n}\n\nmjx-mstyle {\n  display: inline-block;\n}\n\nmjx-merror {\n  display: inline-block;\n  color: red;\n  background-color: yellow;\n}\n\nmjx-mphantom {\n  visibility: hidden;\n}\n\n_::-webkit-full-page-media, _:future, :root mjx-container {\n  will-change: opacity;\n}\n\nmjx-assistive-mml {\n  position: absolute !important;\n  top: 0px;\n  left: 0px;\n  clip: rect(1px, 1px, 1px, 1px);\n  padding: 1px 0px 0px 0px !important;\n  border: 0px !important;\n  display: block !important;\n  width: auto !important;\n  overflow: hidden !important;\n  -webkit-touch-callout: none;\n  -webkit-user-select: none;\n  -khtml-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n}\n\nmjx-assistive-mml[display=\"block\"] {\n  width: 100% !important;\n}\n\nmjx-c::before {\n  display: block;\n  width: 0;\n}\n\n.MJX-TEX {\n  font-family: MJXZERO, MJXTEX;\n}\n\n.TEX-B {\n  font-family: MJXZERO, MJXTEX-B;\n}\n\n.TEX-I {\n  font-family: MJXZERO, MJXTEX-I;\n}\n\n.TEX-MI {\n  font-family: MJXZERO, MJXTEX-MI;\n}\n\n.TEX-BI {\n  font-family: MJXZERO, MJXTEX-BI;\n}\n\n.TEX-S1 {\n  font-family: MJXZERO, MJXTEX-S1;\n}\n\n.TEX-S2 {\n  font-family: MJXZERO, MJXTEX-S2;\n}\n\n.TEX-S3 {\n  font-family: MJXZERO, MJXTEX-S3;\n}\n\n.TEX-S4 {\n  font-family: MJXZERO, MJXTEX-S4;\n}\n\n.TEX-A {\n  font-family: MJXZERO, MJXTEX-A;\n}\n\n.TEX-C {\n  font-family: MJXZERO, MJXTEX-C;\n}\n\n.TEX-CB {\n  font-family: MJXZERO, MJXTEX-CB;\n}\n\n.TEX-FR {\n  font-family: MJXZERO, MJXTEX-FR;\n}\n\n.TEX-FRB {\n  font-family: MJXZERO, MJXTEX-FRB;\n}\n\n.TEX-SS {\n  font-family: MJXZERO, MJXTEX-SS;\n}\n\n.TEX-SSB {\n  font-family: MJXZERO, MJXTEX-SSB;\n}\n\n.TEX-SSI {\n  font-family: MJXZERO, MJXTEX-SSI;\n}\n\n.TEX-SC {\n  font-family: MJXZERO, MJXTEX-SC;\n}\n\n.TEX-T {\n  font-family: MJXZERO, MJXTEX-T;\n}\n\n.TEX-V {\n  font-family: MJXZERO, MJXTEX-V;\n}\n\n.TEX-VB {\n  font-family: MJXZERO, MJXTEX-VB;\n}\n\nmjx-stretchy-v mjx-c, mjx-stretchy-h mjx-c {\n  font-family: MJXZERO, MJXTEX-S1, MJXTEX-S4, MJXTEX, MJXTEX-A ! important;\n}\n\n@font-face /* 0 */ {\n  font-family: MJXZERO;\n  src: url(\"js/output/chtml/fonts/tex-woff-v2/MathJax_Zero.woff\") format(\"woff\");\n}\n\n@font-face /* 1 */ {\n  font-family: MJXTEX;\n  src: url(\"js/output/chtml/fonts/tex-woff-v2/MathJax_Main-Regular.woff\") format(\"woff\");\n}\n\n@font-face /* 2 */ {\n  font-family: MJXTEX-B;\n  src: url(\"js/output/chtml/fonts/tex-woff-v2/MathJax_Main-Bold.woff\") format(\"woff\");\n}\n\n@font-face /* 3 */ {\n  font-family: MJXTEX-I;\n  src: url(\"js/output/chtml/fonts/tex-woff-v2/MathJax_Math-Italic.woff\") format(\"woff\");\n}\n\n@font-face /* 4 */ {\n  font-family: MJXTEX-MI;\n  src: url(\"js/output/chtml/fonts/tex-woff-v2/MathJax_Main-Italic.woff\") format(\"woff\");\n}\n\n@font-face /* 5 */ {\n  font-family: MJXTEX-BI;\n  src: url(\"js/output/chtml/fonts/tex-woff-v2/MathJax_Math-BoldItalic.woff\") format(\"woff\");\n}\n\n@font-face /* 6 */ {\n  font-family: MJXTEX-S1;\n  src: url(\"js/output/chtml/fonts/tex-woff-v2/MathJax_Size1-Regular.woff\") format(\"woff\");\n}\n\n@font-face /* 7 */ {\n  font-family: MJXTEX-S2;\n  src: url(\"js/output/chtml/fonts/tex-woff-v2/MathJax_Size2-Regular.woff\") format(\"woff\");\n}\n\n@font-face /* 8 */ {\n  font-family: MJXTEX-S3;\n  src: url(\"js/output/chtml/fonts/tex-woff-v2/MathJax_Size3-Regular.woff\") format(\"woff\");\n}\n\n@font-face /* 9 */ {\n  font-family: MJXTEX-S4;\n  src: url(\"js/output/chtml/fonts/tex-woff-v2/MathJax_Size4-Regular.woff\") format(\"woff\");\n}\n\n@font-face /* 10 */ {\n  font-family: MJXTEX-A;\n  src: url(\"js/output/chtml/fonts/tex-woff-v2/MathJax_AMS-Regular.woff\") format(\"woff\");\n}\n\n@font-face /* 11 */ {\n  font-family: MJXTEX-C;\n  src: url(\"js/output/chtml/fonts/tex-woff-v2/MathJax_Calligraphic-Regular.woff\") format(\"woff\");\n}\n\n@font-face /* 12 */ {\n  font-family: MJXTEX-CB;\n  src: url(\"js/output/chtml/fonts/tex-woff-v2/MathJax_Calligraphic-Bold.woff\") format(\"woff\");\n}\n\n@font-face /* 13 */ {\n  font-family: MJXTEX-FR;\n  src: url(\"js/output/chtml/fonts/tex-woff-v2/MathJax_Fraktur-Regular.woff\") format(\"woff\");\n}\n\n@font-face /* 14 */ {\n  font-family: MJXTEX-FRB;\n  src: url(\"js/output/chtml/fonts/tex-woff-v2/MathJax_Fraktur-Bold.woff\") format(\"woff\");\n}\n\n@font-face /* 15 */ {\n  font-family: MJXTEX-SS;\n  src: url(\"js/output/chtml/fonts/tex-woff-v2/MathJax_SansSerif-Regular.woff\") format(\"woff\");\n}\n\n@font-face /* 16 */ {\n  font-family: MJXTEX-SSB;\n  src: url(\"js/output/chtml/fonts/tex-woff-v2/MathJax_SansSerif-Bold.woff\") format(\"woff\");\n}\n\n@font-face /* 17 */ {\n  font-family: MJXTEX-SSI;\n  src: url(\"js/output/chtml/fonts/tex-woff-v2/MathJax_SansSerif-Italic.woff\") format(\"woff\");\n}\n\n@font-face /* 18 */ {\n  font-family: MJXTEX-SC;\n  src: url(\"js/output/chtml/fonts/tex-woff-v2/MathJax_Script-Regular.woff\") format(\"woff\");\n}\n\n@font-face /* 19 */ {\n  font-family: MJXTEX-T;\n  src: url(\"js/output/chtml/fonts/tex-woff-v2/MathJax_Typewriter-Regular.woff\") format(\"woff\");\n}\n\n@font-face /* 20 */ {\n  font-family: MJXTEX-V;\n  src: url(\"js/output/chtml/fonts/tex-woff-v2/MathJax_Vector-Regular.woff\") format(\"woff\");\n}\n\n@font-face /* 21 */ {\n  font-family: MJXTEX-VB;\n  src: url(\"js/output/chtml/fonts/tex-woff-v2/MathJax_Vector-Bold.woff\") format(\"woff\");\n}\n</style></head><body><p><em>Cet article est le premier d’une série de quatre dont l’objectif est d’explorer les bases de données graphe et l’évolution du rôle de PostgreSQL dans le domaine. Nous introduirons les concepts fondamentaux puis discuterons de l’implémentation de SQL/PGQ dans PostgreSQL et son avenir. Nous comparerons les performances obtenues face aux solutions graphe sous PostgreSQL (par exemple Apache AGE), puis enfin à la trajectoire plus large des systèmes relationnels intégrant les charges de travail graphe.</em></p><h2 id=\"quest-ce-quun-graphe\"><a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe/#quest-ce-quun-graphe\" class=\"heading-anchor\">Qu’est-ce qu’un graphe ?</a></h2><p><strong>Un graphe est un ensemble d’éléments et un ensemble de connexions entre ces éléments</strong>. La définition est simple!<br>Les éléments sont appelés <em>sommets</em> (ou nœuds) et les connexions sont appelées <em>arêtes</em> (ou relations).</p><p>Formellement, un graphe <mjx-container class=\"MathJax\" jax=\"CHTML\" style=\"font-size: 113.1%; position: relative;\"><mjx-math class=\" MJX-TEX\" aria-hidden=\"true\"><mjx-mi class=\"mjx-i\"><mjx-c class=\"mjx-c1D43A TEX-I\"></mjx-c></mjx-mi></mjx-math><mjx-assistive-mml unselectable=\"on\" display=\"inline\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mi>G</mi></math></mjx-assistive-mml></mjx-container> est modélisé comme un couple <mjx-container class=\"MathJax\" jax=\"CHTML\" style=\"font-size: 113.1%; position: relative;\"><mjx-math class=\" MJX-TEX\" aria-hidden=\"true\"><mjx-mo class=\"mjx-n\"><mjx-c class=\"mjx-c28\"></mjx-c></mjx-mo><mjx-mi class=\"mjx-i\"><mjx-c class=\"mjx-c1D449 TEX-I\"></mjx-c></mjx-mi><mjx-mo class=\"mjx-n\"><mjx-c class=\"mjx-c2C\"></mjx-c></mjx-mo><mjx-mi class=\"mjx-i\" space=\"2\"><mjx-c class=\"mjx-c1D438 TEX-I\"></mjx-c></mjx-mi><mjx-mo class=\"mjx-n\"><mjx-c class=\"mjx-c29\"></mjx-c></mjx-mo></mjx-math><mjx-assistive-mml unselectable=\"on\" display=\"inline\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mo stretchy=\"false\">(</mo><mi>V</mi><mo>,</mo><mi>E</mi><mo stretchy=\"false\">)</mo></math></mjx-assistive-mml></mjx-container>, où <mjx-container class=\"MathJax\" jax=\"CHTML\" style=\"font-size: 113.1%; position: relative;\"><mjx-math class=\" MJX-TEX\" aria-hidden=\"true\"><mjx-mi class=\"mjx-i\"><mjx-c class=\"mjx-c1D449 TEX-I\"></mjx-c></mjx-mi></mjx-math><mjx-assistive-mml unselectable=\"on\" display=\"inline\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mi>V</mi></math></mjx-assistive-mml></mjx-container> est un ensemble de sommets et <mjx-container class=\"MathJax\" jax=\"CHTML\" style=\"font-size: 113.1%; position: relative;\"><mjx-math class=\" MJX-TEX\" aria-hidden=\"true\"><mjx-mi class=\"mjx-i\"><mjx-c class=\"mjx-c1D452 TEX-I\"></mjx-c></mjx-mi></mjx-math><mjx-assistive-mml unselectable=\"on\" display=\"inline\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mi>e</mi></math></mjx-assistive-mml></mjx-container> est un sous-ensemble du produit cartésien de <mjx-container class=\"MathJax\" jax=\"CHTML\" style=\"font-size: 113.1%; position: relative;\"><mjx-math class=\" MJX-TEX\" aria-hidden=\"true\"><mjx-mi class=\"mjx-i\"><mjx-c class=\"mjx-c1D449 TEX-I\"></mjx-c></mjx-mi></mjx-math><mjx-assistive-mml unselectable=\"on\" display=\"inline\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mi>V</mi></math></mjx-assistive-mml></mjx-container> par lui-même, représentant un ensemble d’arêtes :<br><mjx-container class=\"MathJax\" jax=\"CHTML\" style=\"font-size: 113.1%; position: relative;\"><mjx-math class=\" MJX-TEX\" aria-hidden=\"true\"><mjx-mi class=\"mjx-i\"><mjx-c class=\"mjx-c1D438 TEX-I\"></mjx-c></mjx-mi><mjx-mo class=\"mjx-n\" space=\"4\"><mjx-c class=\"mjx-c2286\"></mjx-c></mjx-mo><mjx-mi class=\"mjx-i\" space=\"4\"><mjx-c class=\"mjx-c1D449 TEX-I\"></mjx-c></mjx-mi><mjx-mo class=\"mjx-n\" space=\"3\"><mjx-c class=\"mjx-cD7\"></mjx-c></mjx-mo><mjx-mi class=\"mjx-i\" space=\"3\"><mjx-c class=\"mjx-c1D449 TEX-I\"></mjx-c></mjx-mi></mjx-math><mjx-assistive-mml unselectable=\"on\" display=\"inline\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mi>E</mi><mo>⊆</mo><mi>V</mi><mo>×</mo><mi>V</mi></math></mjx-assistive-mml></mjx-container></p><p>On distingue trois types de graphes : orientés, non orientés et pondérés.</p><ol class=\"list\"><li><p>Pour un <strong>graphe orienté</strong>, une arête <mjx-container class=\"MathJax\" jax=\"CHTML\" style=\"font-size: 113.1%; position: relative;\"><mjx-math class=\" MJX-TEX\" aria-hidden=\"true\"><mjx-mi class=\"mjx-i\"><mjx-c class=\"mjx-c1D452 TEX-I\"></mjx-c></mjx-mi></mjx-math><mjx-assistive-mml unselectable=\"on\" display=\"inline\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mi>e</mi></math></mjx-assistive-mml></mjx-container> est le couple ordonné <mjx-container class=\"MathJax\" jax=\"CHTML\" style=\"font-size: 113.1%; position: relative;\"><mjx-math class=\" MJX-TEX\" aria-hidden=\"true\"><mjx-mo class=\"mjx-n\"><mjx-c class=\"mjx-c28\"></mjx-c></mjx-mo><mjx-mi class=\"mjx-i\"><mjx-c class=\"mjx-c1D462 TEX-I\"></mjx-c></mjx-mi><mjx-mo class=\"mjx-n\"><mjx-c class=\"mjx-c2C\"></mjx-c></mjx-mo><mjx-mi class=\"mjx-i\" space=\"2\"><mjx-c class=\"mjx-c1D463 TEX-I\"></mjx-c></mjx-mi><mjx-mo class=\"mjx-n\"><mjx-c class=\"mjx-c29\"></mjx-c></mjx-mo></mjx-math><mjx-assistive-mml unselectable=\"on\" display=\"inline\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mo stretchy=\"false\">(</mo><mi>u</mi><mo>,</mo><mi>v</mi><mo stretchy=\"false\">)</mo></math></mjx-assistive-mml></mjx-container> dans <mjx-container class=\"MathJax\" jax=\"CHTML\" style=\"font-size: 113.1%; position: relative;\"><mjx-math class=\" MJX-TEX\" aria-hidden=\"true\"><mjx-mi class=\"mjx-i\"><mjx-c class=\"mjx-c1D452 TEX-I\"></mjx-c></mjx-mi></mjx-math><mjx-assistive-mml unselectable=\"on\" display=\"inline\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mi>e</mi></math></mjx-assistive-mml></mjx-container>, où <mjx-container class=\"MathJax\" jax=\"CHTML\" style=\"font-size: 113.1%; position: relative;\"><mjx-math class=\" MJX-TEX\" aria-hidden=\"true\"><mjx-mi class=\"mjx-i\"><mjx-c class=\"mjx-c1D462 TEX-I\"></mjx-c></mjx-mi></mjx-math><mjx-assistive-mml unselectable=\"on\" display=\"inline\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mi>u</mi></math></mjx-assistive-mml></mjx-container> est le sommet source et <mjx-container class=\"MathJax\" jax=\"CHTML\" style=\"font-size: 113.1%; position: relative;\"><mjx-math class=\" MJX-TEX\" aria-hidden=\"true\"><mjx-mi class=\"mjx-i\"><mjx-c class=\"mjx-c1D449 TEX-I\"></mjx-c></mjx-mi></mjx-math><mjx-assistive-mml unselectable=\"on\" display=\"inline\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mi>V</mi></math></mjx-assistive-mml></mjx-container> est le sommet destination; un exemple est l’abonnement sur Twitter, où la relation a une direction spécifique :<br>arête <mjx-container class=\"MathJax\" jax=\"CHTML\" style=\"font-size: 113.1%; position: relative;\"><mjx-math class=\" MJX-TEX\" aria-hidden=\"true\"><mjx-mi class=\"mjx-i\"><mjx-c class=\"mjx-c1D452 TEX-I\"></mjx-c></mjx-mi><mjx-mo class=\"mjx-n\" space=\"4\"><mjx-c class=\"mjx-c3D\"></mjx-c></mjx-mo><mjx-mo class=\"mjx-n\" space=\"4\"><mjx-c class=\"mjx-c28\"></mjx-c></mjx-mo><mjx-mi class=\"mjx-i\"><mjx-c class=\"mjx-c1D462 TEX-I\"></mjx-c></mjx-mi><mjx-mo class=\"mjx-n\"><mjx-c class=\"mjx-c2C\"></mjx-c></mjx-mo><mjx-mi class=\"mjx-i\" space=\"2\"><mjx-c class=\"mjx-c1D463 TEX-I\"></mjx-c></mjx-mi><mjx-mo class=\"mjx-n\"><mjx-c class=\"mjx-c29\"></mjx-c></mjx-mo><mjx-mo class=\"mjx-n\" space=\"4\"><mjx-c class=\"mjx-c2208\"></mjx-c></mjx-mo><mjx-mi class=\"mjx-i\" space=\"4\"><mjx-c class=\"mjx-c1D438 TEX-I\"></mjx-c></mjx-mi></mjx-math><mjx-assistive-mml unselectable=\"on\" display=\"inline\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mi>e</mi><mo>=</mo><mo stretchy=\"false\">(</mo><mi>u</mi><mo>,</mo><mi>v</mi><mo stretchy=\"false\">)</mo><mo>∈</mo><mi>E</mi></math></mjx-assistive-mml></mjx-container></p></li><li><p>Pour un <strong>graphe non orienté</strong>, une arête <mjx-container class=\"MathJax\" jax=\"CHTML\" style=\"font-size: 113.1%; position: relative;\"><mjx-math class=\" MJX-TEX\" aria-hidden=\"true\"><mjx-mi class=\"mjx-i\"><mjx-c class=\"mjx-c1D452 TEX-I\"></mjx-c></mjx-mi></mjx-math><mjx-assistive-mml unselectable=\"on\" display=\"inline\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mi>e</mi></math></mjx-assistive-mml></mjx-container> est un couple non ordonné contenant <mjx-container class=\"MathJax\" jax=\"CHTML\" style=\"font-size: 113.1%; position: relative;\"><mjx-math class=\" MJX-TEX\" aria-hidden=\"true\"><mjx-mi class=\"mjx-i\"><mjx-c class=\"mjx-c1D462 TEX-I\"></mjx-c></mjx-mi></mjx-math><mjx-assistive-mml unselectable=\"on\" display=\"inline\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mi>u</mi></math></mjx-assistive-mml></mjx-container> et <mjx-container class=\"MathJax\" jax=\"CHTML\" style=\"font-size: 113.1%; position: relative;\"><mjx-math class=\" MJX-TEX\" aria-hidden=\"true\"><mjx-mi class=\"mjx-i\"><mjx-c class=\"mjx-c1D449 TEX-I\"></mjx-c></mjx-mi></mjx-math><mjx-assistive-mml unselectable=\"on\" display=\"inline\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mi>V</mi></math></mjx-assistive-mml></mjx-container> dans <mjx-container class=\"MathJax\" jax=\"CHTML\" style=\"font-size: 113.1%; position: relative;\"><mjx-math class=\" MJX-TEX\" aria-hidden=\"true\"><mjx-mi class=\"mjx-i\"><mjx-c class=\"mjx-c1D452 TEX-I\"></mjx-c></mjx-mi></mjx-math><mjx-assistive-mml unselectable=\"on\" display=\"inline\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mi>e</mi></math></mjx-assistive-mml></mjx-container> ; un exemple est l’amitié sur Facebook, où la relation est mutuelle :<br>arête <mjx-container class=\"MathJax\" jax=\"CHTML\" style=\"font-size: 113.1%; position: relative;\"><mjx-math class=\" MJX-TEX\" aria-hidden=\"true\"><mjx-mi class=\"mjx-i\"><mjx-c class=\"mjx-c1D452 TEX-I\"></mjx-c></mjx-mi><mjx-mo class=\"mjx-n\" space=\"4\"><mjx-c class=\"mjx-c3D\"></mjx-c></mjx-mo><mjx-TeXAtom space=\"4\" texclass=\"ORD\"><mjx-mi class=\"mjx-i\"><mjx-c class=\"mjx-c1D462 TEX-I\"></mjx-c></mjx-mi><mjx-mo class=\"mjx-n\"><mjx-c class=\"mjx-c2C\"></mjx-c></mjx-mo><mjx-mi class=\"mjx-i\" space=\"2\"><mjx-c class=\"mjx-c1D463 TEX-I\"></mjx-c></mjx-mi></mjx-TeXAtom><mjx-mo class=\"mjx-n\" space=\"4\"><mjx-c class=\"mjx-c2208\"></mjx-c></mjx-mo><mjx-mi class=\"mjx-i\" space=\"4\"><mjx-c class=\"mjx-c1D438 TEX-I\"></mjx-c></mjx-mi></mjx-math><mjx-assistive-mml unselectable=\"on\" display=\"inline\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mi>e</mi><mo>=</mo><mrow data-mjx-texclass=\"ORD\"><mi>u</mi><mo>,</mo><mi>v</mi></mrow><mo>∈</mo><mi>E</mi></math></mjx-assistive-mml></mjx-container></p></li><li><p>Un <strong>graphe pondéré</strong> étend cette structure en un triplet <mjx-container class=\"MathJax\" jax=\"CHTML\" style=\"font-size: 113.1%; position: relative;\"><mjx-math class=\" MJX-TEX\" aria-hidden=\"true\"><mjx-mo class=\"mjx-n\"><mjx-c class=\"mjx-c28\"></mjx-c></mjx-mo><mjx-mi class=\"mjx-i\"><mjx-c class=\"mjx-c1D449 TEX-I\"></mjx-c></mjx-mi><mjx-mo class=\"mjx-n\"><mjx-c class=\"mjx-c2C\"></mjx-c></mjx-mo><mjx-mi class=\"mjx-i\" space=\"2\"><mjx-c class=\"mjx-c1D438 TEX-I\"></mjx-c></mjx-mi><mjx-mo class=\"mjx-n\"><mjx-c class=\"mjx-c2C\"></mjx-c></mjx-mo><mjx-mi class=\"mjx-i\" space=\"2\"><mjx-c class=\"mjx-c1D464 TEX-I\"></mjx-c></mjx-mi><mjx-mo class=\"mjx-n\"><mjx-c class=\"mjx-c29\"></mjx-c></mjx-mo></mjx-math><mjx-assistive-mml unselectable=\"on\" display=\"inline\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mo stretchy=\"false\">(</mo><mi>V</mi><mo>,</mo><mi>E</mi><mo>,</mo><mi>w</mi><mo stretchy=\"false\">)</mo></math></mjx-assistive-mml></mjx-container>, où <mjx-container class=\"MathJax\" jax=\"CHTML\" style=\"font-size: 113.1%; position: relative;\"><mjx-math class=\" MJX-TEX\" aria-hidden=\"true\"><mjx-mi class=\"mjx-i\"><mjx-c class=\"mjx-c1D464 TEX-I\"></mjx-c></mjx-mi></mjx-math><mjx-assistive-mml unselectable=\"on\" display=\"inline\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mi>w</mi></math></mjx-assistive-mml></mjx-container> est une fonction qui associe à chaque arête dans <mjx-container class=\"MathJax\" jax=\"CHTML\" style=\"font-size: 113.1%; position: relative;\"><mjx-math class=\" MJX-TEX\" aria-hidden=\"true\"><mjx-mi class=\"mjx-i\"><mjx-c class=\"mjx-c1D452 TEX-I\"></mjx-c></mjx-mi></mjx-math><mjx-assistive-mml unselectable=\"on\" display=\"inline\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mi>e</mi></math></mjx-assistive-mml></mjx-container> un nombre réel (un poids), utile pour représenter des distances, des coûts ou des forces :<br>triplet <mjx-container class=\"MathJax\" jax=\"CHTML\" style=\"font-size: 113.1%; position: relative;\"><mjx-math class=\" MJX-TEX\" aria-hidden=\"true\"><mjx-mo class=\"mjx-n\"><mjx-c class=\"mjx-c28\"></mjx-c></mjx-mo><mjx-mi class=\"mjx-i\"><mjx-c class=\"mjx-c1D449 TEX-I\"></mjx-c></mjx-mi><mjx-mo class=\"mjx-n\"><mjx-c class=\"mjx-c2C\"></mjx-c></mjx-mo><mjx-mi class=\"mjx-i\" space=\"2\"><mjx-c class=\"mjx-c1D438 TEX-I\"></mjx-c></mjx-mi><mjx-mo class=\"mjx-n\"><mjx-c class=\"mjx-c2C\"></mjx-c></mjx-mo><mjx-mi class=\"mjx-i\" space=\"2\"><mjx-c class=\"mjx-c1D464 TEX-I\"></mjx-c></mjx-mi><mjx-mo class=\"mjx-n\"><mjx-c class=\"mjx-c29\"></mjx-c></mjx-mo></mjx-math><mjx-assistive-mml unselectable=\"on\" display=\"inline\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mo stretchy=\"false\">(</mo><mi>V</mi><mo>,</mo><mi>E</mi><mo>,</mo><mi>w</mi><mo stretchy=\"false\">)</mo></math></mjx-assistive-mml></mjx-container> où <mjx-container class=\"MathJax\" jax=\"CHTML\" style=\"font-size: 113.1%; position: relative;\"><mjx-math class=\" MJX-TEX\" aria-hidden=\"true\"><mjx-mi class=\"mjx-i\"><mjx-c class=\"mjx-c1D464 TEX-I\"></mjx-c></mjx-mi><mjx-mo class=\"mjx-n\" space=\"4\"><mjx-c class=\"mjx-c3A\"></mjx-c></mjx-mo><mjx-mi class=\"mjx-i\" space=\"4\"><mjx-c class=\"mjx-c1D438 TEX-I\"></mjx-c></mjx-mi><mjx-mo class=\"mjx-n\" space=\"4\"><mjx-c class=\"mjx-c2192\"></mjx-c></mjx-mo><mjx-TeXAtom space=\"4\" texclass=\"ORD\"><mjx-mi class=\"mjx-ds mjx-b\"><mjx-c class=\"mjx-c211D TEX-A\"></mjx-c></mjx-mi></mjx-TeXAtom></mjx-math><mjx-assistive-mml unselectable=\"on\" display=\"inline\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mi>w</mi><mo>:</mo><mi>E</mi><mo accent=\"false\" stretchy=\"false\">→</mo><mrow data-mjx-texclass=\"ORD\"><mi mathvariant=\"double-struck\">R</mi></mrow></math></mjx-assistive-mml></mjx-container></p></li></ol><h2 id=\"ou-sont-les-graphes\"><a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe/#ou-sont-les-graphes\" class=\"heading-anchor\">Où sont les graphes ?</a></h2><p>La puissance du modèle graphe réside dans son universalité. Dès qu’on commence à chercher, les graphes sont partout.</p><ul class=\"list\"><li><strong>Les réseaux sociaux</strong> représentent l’amitié, les abonnements et les interactions comme des arêtes connectant des sommets utilisateurs.<br><em>Savoir si Alice connaît Bob par l’intermédiaire d’autres personnes</em><br><em>est essentiellement un parcours du graphe pour trouver cette relation.</em></li></ul><ul class=\"list\"><li><p><strong>Les systèmes de détection de fraude</strong> modélisent les transactions bancaires entre comptes sous forme de graphes. Les activités frauduleuses génèrent des structures particulières très faciles à repérer telles des cycles ou des amas denses de relations transactions-comptes.<br><em>Les relations entre entités révèlent souvent la fraude plus fiablement que les entités elles-mêmes.</em></p></li><li><p><strong>Les chaînes d’approvisionnement et la logistique</strong> utilisent les graphes pour modéliser les dépendances entre fournisseurs, entrepôts et expéditions.</p></li><li><p>Les biologistes représentent <strong>les réseaux d’interaction protéique et les relations médicament-cible</strong>.<br><img src=\"https://www.data-bene.io/assets/images/blog/protein_network_transparent.png\" alt=\"protein_network_transparent\" width=\"80%\" eleventy:widths=\"650,960,1400\"></p></li><li><p><strong>Les réseaux informatiques</strong> utilisent les graphes pour représenter les topologies.</p></li></ul><p><img src=\"https://www.data-bene.io/assets/images/blog/stp_topology_transparent.png\" alt=\"stp_topology_transparent\" width=\"80%\" eleventy:widths=\"650,960,1400\"></p><ul class=\"list\"><li><strong>Le Web</strong> est un autre exemple de graphe.<br><em>Les pages sont des sommets, les hyperliens sont des arêtes orientées, et le graphe résultant est l’une des structures les plus vastes et les plus étudiées en informatique</em> :</li></ul><p><img src=\"https://www.data-bene.io/assets/images/blog/web_graph_transparent.png\" alt=\"web_graph_transparent\" width=\"80%\" eleventy:widths=\"650,960,1400\"></p><h2 id=\"modeliser-comme-un-graphe\"><a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe/#modeliser-comme-un-graphe\" class=\"heading-anchor\">Modéliser comme un graphe</a></h2><p>Ce que partagent les exemples de domaines ci-dessus sont des <strong>propriétés</strong> qui font du <strong>graphe</strong> une solution intuitive pour nous, êtres humains. Les relations sont aussi importantes que les entités elles-mêmes.<br>Le schéma est souvent irrégulier ou évolutif. Les <strong>requêtes</strong> suivent fréquemment des chaînes de connexions dont la longueur ou la forme n’est pas connue à l’avance.</p><p><strong>Les graphes sont également efficaces parce qu’ils sont faciles à raisonner visuellement</strong>. Les êtres humains comprennent mieux les choses avec des exemples, et un graphe rend les relations explicites. Cette clarté visuelle et structurelle se traduit souvent par des modèles de données et des algorithmes plus faciles à expliquer et à questionner.</p><p>Le modèle défini au début de cet article, un ensemble de sommets et un ensemble d’arêtes sans donnée attachée, sous-tend une grande partie de la théorie classique des graphes et constitue la base des frameworks de traitement de graphes et des systèmes de gestion de bases de données graphe. Il est toutefois trop limité pour la plupart des scénarios de bases de données réels, car il ne transporte aucune information au-delà de la structure. Les modèles plus riches utilisés dans les bases de données graphe sont construits sur cette base.</p><ul class=\"list\"><li>Le <strong>Labeled Property Graph (LPG)</strong> est le modèle conceptuel standard utilisé par la plupart des systèmes de bases de données graphe. Il enrichit le graphe simple par deux mécanismes : les <strong>labels</strong>, qui classent les sommets et les arêtes en types, et les <strong>propriétés</strong>, qui attachent des données arbitraires de type clé-valeur aux sommets et aux arêtes individuels.<br>Un sommet pourrait avoir le label <code>Person</code> et les propriétés <code>name='Alice'</code> et <code>age=21</code>.<br>Une arête pourrait avoir le label <code>KNOWS</code> et la propriété <code>since = \"09.08.2007\"</code>.</li></ul><p><a href=\"https://dl.acm.org/doi/10.1145/3604932#sec-3-3-2\" target=\"_blank\" rel=\"noopener\"><img src=\"https://www.data-bene.io/assets/images/blog/csur-2022-0455-f02.png\" alt=\"Exemple de Labeled Property Graph, adapté de Besta et al.\" width=\"80%\" eleventy:widths=\"650,960,1400\"></a></p><p>D’autres variantes du LPG sont implémentées par d’autres systèmes avec de légères extensions ou restrictions ; par exemple, <a href=\"https://neo4j.com/\" target=\"_blank\" rel=\"noopener\">Neo4j</a> prend en charge un nombre arbitraire de labels par sommet mais limite les arêtes à exactement un label.</p><ul class=\"list\"><li>Le <strong>Resource Description Framework (RDF)</strong> adopte une approche différente. Le RDF représente l’information comme des collections de triplets sujet, prédicat, objet <mjx-container class=\"MathJax\" jax=\"CHTML\" style=\"font-size: 113.1%; position: relative;\"><mjx-math class=\" MJX-TEX\" aria-hidden=\"true\"><mjx-mo class=\"mjx-n\"><mjx-c class=\"mjx-c28\"></mjx-c></mjx-mo><mjx-mi class=\"mjx-i\"><mjx-c class=\"mjx-c1D460 TEX-I\"></mjx-c></mjx-mi><mjx-mo class=\"mjx-n\"><mjx-c class=\"mjx-c2C\"></mjx-c></mjx-mo><mjx-mi class=\"mjx-i\" space=\"2\"><mjx-c class=\"mjx-c1D45D TEX-I\"></mjx-c></mjx-mi><mjx-mo class=\"mjx-n\"><mjx-c class=\"mjx-c2C\"></mjx-c></mjx-mo><mjx-mi class=\"mjx-i\" space=\"2\"><mjx-c class=\"mjx-c1D45C TEX-I\"></mjx-c></mjx-mi><mjx-mo class=\"mjx-n\"><mjx-c class=\"mjx-c29\"></mjx-c></mjx-mo></mjx-math><mjx-assistive-mml unselectable=\"on\" display=\"inline\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mo stretchy=\"false\">(</mo><mi>s</mi><mo>,</mo><mi>p</mi><mo>,</mo><mi>o</mi><mo stretchy=\"false\">)</mo></math></mjx-assistive-mml></mjx-container>.<br>Si les systèmes basés sur le RDF constituent une part significative du paysage des bases de données graphe, ils suivent un modèle de données différent du LPG et <strong>sont hors du cadre de cette série</strong>. Nous le mentionnons uniquement pour le contexte, cette série d’articles étant centrée sur les bases de données graphe de type “labeled property graph”.</li></ul><h2 id=\"les-nombreuses-formes-des-bases-de-donnees-graphe\"><a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe/#les-nombreuses-formes-des-bases-de-donnees-graphe\" class=\"heading-anchor\">Les nombreuses formes des bases de données graphe</a></h2><p>Le paysage des bases de données graphe est hétérogène. Les systèmes diffèrent fondamentalement dans la manière dont ils stockent les graphes, les modèles de données qu’ils supportent et les langages de requête qu’ils exposent.</p><p><a href=\"https://dl.acm.org/doi/10.1145/3604932#sec-5\" target=\"_blank\" rel=\"noopener\"><img src=\"https://www.data-bene.io/assets/images/blog/graph_db_models_transparent.png\" alt=\"Aperçu des différents backends de stockage graphe\" width=\"80%\" eleventy:widths=\"650,960,1400\"></a></p><p><strong>Les bases de données graphe natives</strong> sont conçues de A à Z autour du modèle graphe. Leurs schémas de stockage et leurs moteurs de requête sont pensés avec les schémas d’accès aux graphes comme préoccupation principale : elles visent à « suivre les pointeurs », ou à accéder à l’adjacence directement, de sorte que la navigation « ne devienne pas un JOIN ».<br>Neo4j en est l’exemple le plus marquant. Pendant longtemps, son moteur de stockage utilisait des enregistrements de taille fixe avec des pointeurs directs entre eux, et c’était essentiellement ainsi que les gens décrivaient le stockage graphe natif.<br>Après une quinzaine d’années, en 2024, Neo4j a introduit un format de blocs qui co-localise les données apparentées dans des blocs de longueur variable à l’intérieur de pages <sup class=\"footnote-ref\"><a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe/#fn1\" id=\"fnref1\">[1]</a></sup>. Bien que cette prise de conscience tardive soit un progrès, elle implique que la description « natif équivaut à suivre des pointeurs » n’est plus tout à fait exacte.<br>La définition utile devrait donc être comportementale, c’est-à-dire que les systèmes natifs tentent de rendre l’accès à l’adjacence direct, que ce soit par des pointeurs, des blocs co-localisés ou d’autres schémas spécifiques aux graphes.</p><p><strong>Les bases de données graphe non natives</strong> reprennent un backend mature existant ; une base relationnelle, orientée document ou clé-valeur, et construisent des capacités graphe par-dessus <sup class=\"footnote-ref\"><a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe/#fn2\" id=\"fnref2\">[2]</a></sup>. Les deux classes sont des bases de données graphe au sens où elles stockent, interrogent et gèrent des données de type graphe, mais leurs composants internes sont fondamentalement différents, ce qui implique que des optimisations spécifiques aux graphes sont disponibles, adapatées au backend.<br>En pratique, la différence porte davantage sur l’endroit où l’effort d’ingénierie est investi : par exemple, les systèmes non natifs héritent de décennies de travail en contrôle de concurrence, indexation, optimisation des requêtes et bien d’autres composants de SGBD.</p><hr><p><strong>Une étude</strong> d’une centaine de systèmes de bases de données graphe révèle qu’environ 66 % sont non natifs. La répartition des modèles de données sous-jacents se décompose comme suit : 34 % de stockage graphe natif, 24 % de bases de données relationnelles, 24 % de stockages clé-valeur ou à colonnes larges, et 18 % de stockages orientés document. Cela a du sens : on souhaite rendre un SGBD existant capable de supporter les requêtes graphe si possible, offrant ainsi aux utilisateurs la meilleure interface possible.</p><p>C’est précisément à cet endroit que PostgreSQL entre en jeu. En tant que base de données relationnelle mature, elle représente une part massive de cet écosystème non natif à travers des extensions et de nouvelles normes SQL.</p><h2 id=\"points-cles\"><a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe/#points-cles\" class=\"heading-anchor\">Points clés</a></h2><p>Avant de passer à l’implémentation technique, rappelons les concepts fondamentaux de cette introduction :</p><ul class=\"list\"><li><strong>Les graphes sont universels :</strong> Au fond, ils ne sont que des sommets (nœuds) et des arêtes (relations), ce qui les rend idéaux pour des données complexes et interconnectées comme les réseaux sociaux ou les réseaux de fraude.</li><li><strong>Le LPG est la norme de l’industrie :</strong> Le modèle Labeled Property Graph étend les graphes simples en permettant d’attacher des labels et des propriétés clé-valeur aux nœuds et aux arêtes.</li><li><strong>Natif vs. non-natif est une distinction comportementale :</strong> Les bases de données natives (comme Neo4j) optimisent l’accès direct à l’adjacence, tandis que les bases non natives exploitent des moteurs de niveau entreprise existants (relationnels, orientés document) pour traiter les charges de travail graphe.</li><li><strong>Le paysage est hybride :</strong> Plus de 66 % des solutions de bases de données graphe sont construites sur des backends non graphe, prouvant qu’il n’est pas toujours nécessaire de déployer une nouvelle base de données native pour interroger des structures de type graphe.</li></ul><h2 id=\"et-maintenant\"><a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe/#et-maintenant\" class=\"heading-anchor\">Et maintenant ?</a></h2><p>Maintenant que nous avons posé le vocabulaire de base, nous pouvons explorer comment intégrer ce modèle dans le monde relationnel. Dans <a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe-part-1/\">la <strong>partie 1</strong></a>, nous plongerons directement dans <strong>SQL/PGQ dans PostgreSQL</strong> : ce que cette nouvelle norme apporte, comment elle est implémentée en interne, et les limitations actuelles.</p><hr class=\"footnotes-sep\"><section class=\"footnotes\"><ol class=\"footnotes-list\"><li id=\"fn1\" class=\"footnote-item\"><p><a href=\"https://neo4j.com/docs/operations-manual/current/database-internals/store-formats/\" target=\"_blank\" rel=\"noopener\">Neo4j store formats</a> <a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe/#fnref1\" class=\"footnote-backref\">↩︎</a></p></li><li id=\"fn2\" class=\"footnote-item\"><p>Plusieurs images empruntées à <a href=\"https://dl.acm.org/doi/10.1145/3604932\" target=\"_blank\" rel=\"noopener\">Besta, M. et al. (2023). Demystifying Graph Databases: Analysis and Taxonomy of Data Organization, System Designs, and Graph Queries. <em>ACM Computing Surveys</em>, 56(2), Art. 31.</a> <a href=\"https://www.data-bene.io/fr/blog/postgresql-comme-bdd-graphe/#fnref2\" class=\"footnote-backref\">↩︎</a></p></li></ol></section></body></html>\n",
      "date_published": "2026-10-19T00:00:00Z"
    }
    ,{
      "id": "https://www.data-bene.io/fr/blog/ivorysql-5/",
      "url": "https://www.data-bene.io/fr/blog/ivorysql-5/",
      "title": "IvorySQL 5.0+ : un tournant pour les transitions Oracle vers PostgreSQL",
      "content_html": "\n<html><head></head><body><p>IvorySQL : « un PostgreSQL avancé, complet, open source, compatible Oracle, avec un engagement ferme de rester toujours 100% compatible et un remplacement direct de la dernière version de PostgreSQL. » (<a href=\"https://github.com/IvorySQL/IvorySQL\" rel=\"noopener\">GitHub</a>)</p><p>C’est aussi le moteur préféré de notre équipe pour traduire à la fois le SQL étranger et les applications étrangères pour PostgreSQL ! Nous croyons en les transitions, pas les migrations — un déplacement progressif de l’ancien moteur de base de données vers le nouveau, spécifiquement pour réduire les risques et optimiser les résultats. Utiliser un projet comme celui-ci fait toute la différence pour atteindre ces deux objectifs.</p><p>La dernière version majeure est sortie il y a un peu de temps, mais nous sommes toujours enthousiastes quant à ce qui est nouveau et nous avons tenu à le partager.</p><h2 id=\"nouveautes\"><a href=\"https://www.data-bene.io/fr/blog/ivorysql-5/#nouveautes\" class=\"heading-anchor\">Nouveautés</a></h2><p>La version 5.0 (<a href=\"https://github.com/IvorySQL/IvorySQL/releases/tag/IvorySQL_5.0\" rel=\"noopener\">notes de version</a>) est sortie le 25 novembre 2025 et une version mineure a déjà été publiée depuis (<a href=\"https://github.com/IvorySQL/IvorySQL/releases/tag/IvorySQL_5.1\" rel=\"noopener\">notes de version 5.1</a>) le 18 décembre 2025. Ces éditions du projet sont le résultat direct des efforts massifs de l’équipe IvorySQL pour fournir de nombreuses améliorations de qualité ainsi que pour implémenter la compatibilité avec PostgreSQL 18.</p><p>IvorySQL 5 a apporté de nombreux changements nécessaires, notamment :</p><ul class=\"list\"><li><strong>PLiSQL</strong> — un sous-ensemble compatible d’Oracle PL/SQL</li><li><strong>Support des paquets compatibles Oracle</strong></li><li><strong>Support des séquences style Oracle</strong></li><li>les améliorations de v5.0 telles que <strong>ROWID</strong>, <strong>%TYPE</strong>, <strong>%ROWTYPE</strong> et <strong>les sous-fonctions imbriquées</strong></li></ul><p>En particulier, nous apprécions beaucoup les améliorations fonctionnelles.</p><p>Par exemple, IvorySQL dispose désormais d’un <strong>meilleur traitement des valeurs NULL</strong>, où NULL est désormais traité comme une chaîne vide en mode compatible (correspondant au comportement Oracle) pour éviter des bugs lors de la migration. Ainsi, dans des situations telles que <code>SELECT CONCAT('a' || NULL)</code>, IvorySQL retournera désormais <code>'a'</code> au lieu de suivre le comportement de PostgreSQL qui retournerait <code>NULL</code>.</p><p>Une amélioration que nous apprécions particulièrement est qu’il est désormais possible <strong>d’imbriquer des fonctions et des procédures</strong>. Les fonctions peuvent être intégrées dans d’autres fonctions (à la manière des paquets Oracle, mais plus simplement, en utilisant uniquement des méthodes privées). Cela permet d’organiser une logique complexe en un seul endroit.</p><p>Dans le même ordre d’idées, le support a également été ajouté pour <code>DO [ LANGUAGE lang_name ] code [USING IN | OUT | IN OUT, ...]</code>.</p><h2 id=\"lessayer\"><a href=\"https://www.data-bene.io/fr/blog/ivorysql-5/#lessayer\" class=\"heading-anchor\">L’essayer</a></h2><p>Actuellement, nous intégrons des applications allant de quelques paquets, procédures et fonctions (environ 10 à 50 objets) à des chargements de données massifs incluant environ 50 000 objets (plus de 10 000 procédures et des centaines de paquets).</p><p>Bien que de nombreuses fonctionnalités devront encore être ajoutées avec le temps, cela réduit considérablement l’effort nécessaire pour achever avec succès la transition d’Oracle vers PostgreSQL.</p><p>Si vous envisagez de le tester vous-même, il existe une pléthore d’options pour commencer (y compris la compilation depuis la source, l’utilisation de conteneurs, etc.)… et même une compilation WASM ! En particulier, cela permet d’exécuter IvorySQL directement dans le navigateur sans avoir à l’installer localement ; c’est très pratique pour examiner le support de syntaxe et faire le premier pas vers le monde de PostgreSQL.</p><p>Vous pouvez déployer le projet IvorySQL-WASM localement en quelques étapes, en suivant <a href=\"https://www.ivorysql.org/blog/ivorysql-wasm/\" rel=\"noopener\">le billet de blog publié par IvorySQL</a> sur le sujet.</p><p>Sinon, vous pouvez <a href=\"https://trial.ivorysql.org/\" rel=\"noopener\">essayer le WASM hébergé</a> sur le site web d’IvorySQL.</p><h2 id=\"et-la-suite\"><a href=\"https://www.data-bene.io/fr/blog/ivorysql-5/#et-la-suite\" class=\"heading-anchor\">Et la suite ?</a></h2><p>Vous souhaitez en apprendre davantage sur l’utilisation d’IvorySQL ? Restez à l’affût des webinaires enregistrés sur leur site web (<a href=\"https://www.ivorysql.org/webinars-page\" rel=\"noopener\">à venir !</a>), ou <a href=\"https://www.youtube.com/@ivorysql\" rel=\"noopener\">consultez les enregistrements</a> de la conférence HOW2025 à Jinan, en Chine, en attendant.</p><p><a href=\"https://ivorysql.io/\" rel=\"noopener\">La prochaine conférence à Jinan</a> est déjà prévue, du 26 au 28 avril ! (Au passage, <a href=\"https://sessionize.com/how2026\" rel=\"noopener\">l’appel à contributions est ouvert</a> jusqu’au 27 février 2026.)</p><p>Notre équipe est heureuse d’employer des contributeurs au projet IvorySQL. Certains de nos membres (Cédric Villemain, Yasir Hussain Shah) ont été reconnus dans les notes de version de 5.0 et 5.1 — et nous avons d’autres ajouts prévus. Pour la prochaine version, nous avons prévu des développements passionnants, notamment :</p><ul class=\"list\"><li>la syntaxe de contrainte <code>ENABLE/DISABLE</code></li><li>l’ajout du paquet <code>UTL_FILE</code></li><li>le corps de <code>CREATE TRIGGER</code> style Oracle (sans avoir besoin de créer une fonction au préalable)</li><li>le support de l’opérateur de jointure legacy d’Oracle <code>(+)</code></li></ul><p>Nous avons hâte de voir les résultats du travail communautaire en cours pour la prochaine version. De nombreuses fonctionnalités excellentes sont activement ajoutées ; par exemple, récemment, un nouveau contributeur au projet, Rophy Tsai, a ajouté les paquets <code>DBMS_OUTPUT</code> et <code>DBMS_UTILITY</code> : des éléments largement utilisés dans les bases de code SQL basées sur Oracle. Ils ont récemment été fusionnés dans la branche principale d’IvorySQL et seront probablement inclus dans la prochaine version mineure ou majeure.</p><p>Pour ceux qui souhaitent passer à PostgreSQL ou l’explorer sans modifications importantes de leur logique de base de données et de leurs applications existantes, IvorySQL (en particulier v5.x) offre une solution pratique. Une migration directe vers PostgreSQL pourrait, dans certains cas, nécessiter des changements importants tant au niveau des objets de base de données qu’au niveau du code applicatif. IvorySQL aide à combler cet écart, permettant une adoption plus fluide de PostgreSQL avec une plus grande compatibilité.</p><h2 id=\"ressources-complementaires\"><a href=\"https://www.data-bene.io/fr/blog/ivorysql-5/#ressources-complementaires\" class=\"heading-anchor\">Ressources complémentaires</a></h2><ul class=\"list\"><li><a href=\"https://www.postgresql.org/about/news/ivorysql-50-released-major-oracle-compatibility-expansion-on-postgresql-180-foundation-3180/\" rel=\"noopener\">Annonce PostgreSQL.org pour IvorySQL 5</a></li><li><a href=\"https://github.com/orgs/IvorySQL/projects/19\" rel=\"noopener\">Feuille de route d’IvorySQL 5.0 sur GitHub</a></li></ul></body></html>\n",
      "date_published": "2026-01-27T00:00:00Z"
    }
    ,{
      "id": "https://www.data-bene.io/fr/blog/pgday-cern-2026/",
      "url": "https://www.data-bene.io/fr/blog/pgday-cern-2026/",
      "title": "CERN PGDay : un événement PostgreSQL annuel à Genève, Suisse",
      "content_html": "\n<html><head></head><body><p>Si vous résidez près de l’ouest de la Suisse et de la région de Genève (ou que vous souhaitez simplement visiter le coin!), vous tirerez probablement tout intérêt à assister au <a href=\"https://www.swisspug.org/cern-pgday-2026.html\" rel=\"noopener\">CERN PGDay 2026</a>. Il s’agit d’une rencontre annuelle (cette année le 6 février 2026) destinée à toute personne souhaitant en apprendre plus sur PostgreSQL, qui se tient au CERN, le plus grand laboratoire de physique des particules au monde.</p><p><em>Si le sujet de la physique des particules vous intéresse, vous voudrez peut-être venir de toute façon ! Le CERN offre un accès gratuit à de nombreuses activités du mardi au dimanche ; <a href=\"https://visit.cern/programme\" rel=\"noopener\">vous pouvez consulter le programme complet ici</a>.</em></p><p>Vous pourrez assister à une série de sept sessions en anglais, suivies d’une rencontre sociale pour profiter du CERN tout en continuant à discuter avec les autres participants.</p><p>Cette année, le programme inclura :</p><ol class=\"list\"><li><strong>Un nouveau backend PostgreSQL pour l’ordonnancement de l’archive CERN Tape à destination de la campagne 4 du LHC</strong> — Konstantina Skovola, CERN</li><li><strong>DCS Data Tools — implémentation PostgreSQL/TimescaleDB pour les données temporelles ATLAS DCS</strong> — Dimitrios Matakias, Paris Moschovakos, CERN</li><li><strong>Les risques opérationnels de la gestion de bases PostgreSQL de plus de 100 To</strong> — Teresa Lopes, Adyen</li><li><strong>Le vidage de grandes tables : comment les changements récents de Postgres facilitent davantage les charges de travail critiques</strong> — Robert Treat, AWS</li><li><strong>Le paysage (très pratique) du sharding Postgres</strong> — Álvaro Hernández, OnGres</li><li><strong>L’alchimie des shared buffers : équilibrer concurrence et performances</strong> — Josef Machytka, credativ</li><li><strong>Quand Kafka a rencontré l’Éléphant : une histoire d’amour sur l’ingestion rapide</strong> — Barbora Linhartova, Jan Suchanek, Baremon</li></ol><p>La première intervention de la journée est particulièrement notoire…</p><blockquote><p>L’archive CERN Tape (CTA) stocke plus d’un exaoctet de données scientifiques. Pour orchestrer les opérations de stockage (archivage) et les opérations d’accès (récupération), l’ordonnanceur CTA coordonne des mouvements de données concurrents sur des centaines de serveurs bande, en s’appuyant sur une base de données d’ordonnancement (Scheduler DB) pour gérer les métadonnées des requêtes en cours. L’architecture existante basée sur un “objectstore” de la base de données d’ordonnancement CTA est un système de gestion transactionnelle complexe. Cette présentation présente le développement d’un nouveau backend PostgreSQL pour l’ordonnanceur CTA comme solution prête à l’emploi qui simplifie l’implémentation et devrait réduire significativement les coûts de développement et opérationnels futurs. Nous décrivons l’implémentation de tous les principaux flux de travail CTA et expliquons comment PostgreSQL répond aux limitations du système basé sur un objectstore, offrant les fondations pour l’augmentation décuplée du débit de données attendue durant la campagne 4 du LHC.</p></blockquote><p><em>(<a href=\"https://indico.cern.ch/event/1504097/contributions/6833857/\" rel=\"noopener\">lien vers la description de l’intervention</a>)</em></p><p>Dans un monde où des quantités toujours plus importantes d’informations numériques doivent être stockées, en apprendre davantage sur la manière dont le CERN gère plus d’un exaoctet de données scientifiques s’avérera sûrement une expérience intéressante.</p><p>Genève accueille de nombreuses organisations internationales dans les secteurs public, privé et scientifique. Si vous souhaitez explorer plus en profondeur le sujet de PostgreSQL par le biais de discussions ou de sessions, c’est un lieu agréable pour rencontrer des personnes et apprendre. Vous pensez venir ? Vous pouvez <a href=\"https://indico.cern.ch/event/1504097/registrations/114102/\" rel=\"noopener\">vous inscrire jusqu’au 1er février</a>.</p><p>Les enregistrements des sessions de l’année dernière peuvent être consultés en <a href=\"https://indico.cern.ch/event/1471762/timetable/#20250117\" rel=\"noopener\">visitant le programme 2025</a> et en sélectionnant le trombone à côté de l’intervention qui vous intéresse.</p><p>Passez nous voir dans la zone de restauration ; nous sommes fiers de sponsoriser à nouveau l’événement cette année et aurons un stand ou un comptoir où vous pourrez nous rendre visite. Nous serions ravis de discuter de PostgreSQL, de l’innovation et du développement open-source, ainsi que de répondre à toutes vos questions.</p></body></html>\n",
      "date_published": "2026-01-22T00:00:00Z"
    }
    ,{
      "id": "https://www.data-bene.io/fr/blog/optimisation-base-de-donnees-et-pollution-mondiale/",
      "url": "https://www.data-bene.io/fr/blog/optimisation-base-de-donnees-et-pollution-mondiale/",
      "title": "L&#39;optimisation des bases de données et l&#39;importance de réduire la pollution numérique mondiale",
      "content_html": "\n<html><head></head><body><p>Je repensais au <a href=\"https://pgibz.io/\" rel=\"noopener\">Postgres Ibiza (PGIBZ)</a> qui a eu lieu il y a quelques mois… Et pas seulement parce que la chaleur et le soleil d’Ibiza me manquent, l’hiver étant arrivé à Cognac ! Non, je me souvenais que l’île portait encore les traces des récentes inondations, même si les habitants s’activaient pour effacer les dégâts. Les dernières nouvelles des Caraïbes et d’Asie m’ont fait réaliser qu’Ibiza avait, toutes proportions gardées, été plutôt chanceuse.</p><p>Cet événement fait partie d’une succession d’évènements climatiques exceptionnels et de records battus aux États-Unis, en Europe et en Asie ces dernières années. La semaine dernière encore, au moment de la rédaction de cet article, l’État de Washington (États-Unis) a connu des inondations historiques qui ont causé des dégâts considérables : plus de 11 millards de m³ d’eau se sont déversés sur l’État en dix jours. Ces pluies torrentielles devraient se poursuivre sur toute la côte ouest américaine jusqu’à la fin de l’année.</p><p>J’ignore si ce contexte a influencé la réception de mon intervention lors de la conférence, et je suis reconnaissante qu’elle ait non seulement été entendue, mais aussi écoutée, et même qu’elle ait suscité des réflexions et des discussions. Je dois avouer que je ne m’y attendais pas.</p><p>Je fais partie de ceux qui pensent que les défis environnementaux sont sur le point de transformer radicalement nos sociétés à tous les niveaux et à l’échelle planétaire, à mesure que les ressources se raréfient et se redistribuent. Je me demande si d’autres se posent la même question : « À quoi bon un salaire confortable si les pommes de terre ne poussent plus ? » Maslow a clairement démontré qu’il est moins important d’être riche que de se nourrir. Pourtant, comme nous le savons, l’environnement n’est toujours pas une priorité absolue, malgré tout ce que nous voyons arriver.</p><p>Il me semblait donc logique d’aborder ce sujet lors d’une conférence PostgreSQL, car il devrait être discuté partout. Mais étais-je certaine de trouver un public réceptif ? Absolument pas !</p><p>Je me sentais un peu mal à l’aise – comme souvent lors de conférences vu mon manque de backgroud technique – à l’idée d’emmener le public sur un terrain qui n’était pas forcément celui qu’il recherchait. J’espérais ne pas ennuyer, déranger, ni même agacer. Mais dès les premières diapositives, j’ai vu que les gens prenaient des photos des données que je présentais, certains acquiesçaient, d’autres découvraient ces chiffres pour la première fois et haussaient un sourcil. Et quand j’ai fait le lien avec nos activités quotidiennes et l’impact de la pollution numérique que nous produisons, au lieu de susciter l’indifférence ou la désapprobation, j’ai eu droit à des regards intéressés, du genre « pourquoi pas ! ».</p><h2 id=\"alors-quelle-pollution-numerique-produisons-nous\"><a href=\"https://www.data-bene.io/fr/blog/optimisation-base-de-donnees-et-pollution-mondiale/#alors-quelle-pollution-numerique-produisons-nous\" class=\"heading-anchor\">Alors quelle pollution numérique produisons-nous ?</a></h2><p>Selon Greenpeace, la pollution numérique désigne toutes les formes de pollution causées par le secteur informatique : émissions de gaz à effet de serre, contamination chimique, érosion de la biodiversité et production de déchets électroniques.</p><p>Oui, des solutions sont conçues pour que les data centers utilisent la chaleur qu’ils produisent afin de chauffer les bureaux ou les habitations avoisinantes, ce qui fonctionne en hiver. Des projets comme celui d’Amazon à Tallaght constituent « le premier réseau de chauffage urbain à grande échelle de ce type en Irlande », contribuant à « réduire considérablement les émissions dans la région de près de 1 500 tonnes de CO2/an, faisant de Tallaght un chef de file en matière d’action énergétique locale » (<a href=\"https://www.seai.ie/case-studies/tallaght-district-heating\" rel=\"noopener\">source</a>).</p><p>Cependant, la croissance du nombre d’utilisateurs équipés d’au moins un terminal connecté (notamment dans les pays en développement), l’augmentation du ratio terminaux connectés/individu (de 2,1 en 2015 à 3,3 en 2020 en moyenne dans le monde), la hausse du trafic vidéo, conjuguée à la part croissante des images en HD et UHD, et le passage à la consommation à la demande (streaming, VOD, cloud gaming) ont entraîné une explosion du trafic sur les réseaux (plus de 25 % par an) et dans les data centers (+35 % par an). Cette croissance est plus rapide que les gains d’efficacité énergétique des équipements, des réseaux et des centres de données. Ces prévisions de trafic sont d’ailleurs régulièrement revues à la hausse.</p><p>Bien que le nombre d’appareils « standard » (hors objets connectés) ait augmenté de manière significative entre 2000 et 2015, il se stabilise entre 2015 et 2025 car le marché est saturé.</p><p>Bien que la masse par utilisateur diminue légèrement, passant de 63 kg d’émissions de CO2 à 58 kg entre 2010 et 2025, la masse totale (équipements utilisateurs, réseaux, data centers) a été multipliée par plus de 2,5 en 15 ans : elle passe de 128 millions de tonnes en 2010 à 317 millions de tonnes en 2025.</p><p>Ceci explique la pression exercée sur les matières premières, notamment les « minerais de conflit » et autres terres rares.</p><h2 id=\"la-cle-dun-monde-plus-vert\"><a href=\"https://www.data-bene.io/fr/blog/optimisation-base-de-donnees-et-pollution-mondiale/#la-cle-dun-monde-plus-vert\" class=\"heading-anchor\">La clé d’un monde plus vert</a></h2><p>L’optimisation des performances des bases de données ne se limite pas à une amélioration des coûts et de la vitesse. En optimisant une requête, on économise l’énergie superflue utilisée pour les opérations de lecture/écriture et les déplacements inutiles sur le disque. D’autres pratiques responsables, qui permettent d’exploiter intelligemment la puissance de la technologie, contribuent non seulement à une meilleure efficacité technique, mais aussi, souvent inconsciemment, à la protection de l’environnement.</p><p>Par exemple, certaines actions que nous entreprenons régulièrement et qui ont également un impact positif sur notre planète incluent :</p><ul class=\"list\"><li>l’optimisation des requêtes</li><li>l’optimisation des index</li><li>la réalisation d’audits de performance pour identifier les goulots d’étranglement et les problèmes</li><li>le choix de technologies moins énergivores</li><li>la réduction de l’empreinte des données (suppression des données redondantes, corrompues ou inutiles)</li><li>l’optimisation de l’infrastructure de stockage et de la puissance de calcul afin de réduire la consommation d’énergie</li></ul><p>Nous nous devons de considérer la sobriété numérique comme la clé de voute pour un code plus écologique et nous pouvons décider d’intégrer ce paramètre dans notre façon de travailler au quotidien et dans la façon dont nous concevons, gérons et développons des solutions de bases de données qui minimisent autant que possible notre empreinte environnementale.</p><p>Une remarque supplémentaire : l’IA, en particulier, entraîne une forte augmentation de la consommation d’eau, des émissions de CO2 et des déchets électroniques (l’entraînement des modèles d’IA est l’une des tâches les plus gourmandes en ressources au monde !). Dans un monde où l’IA est devenue omniprésente dans les applications et les pratiques de programmation quotidiennes, il est crucial d’utiliser ces technologies avec discernement afin de s’assurer qu’elles constituent réellement la meilleure solution au problème posé. L’IA est-elle vraiment la solution la plus appropriée au problème que vous avez en tête ? Ou envisagez-vous son utilisation simplement parce qu’elle est plus facile à mettre en œuvre qu’une solution plus complexe techniquement ?</p><h2 id=\"cest-a-vous\"><a href=\"https://www.data-bene.io/fr/blog/optimisation-base-de-donnees-et-pollution-mondiale/#cest-a-vous\" class=\"heading-anchor\">C’est à Vous !</a></h2><p>Je propose cette perspective sur nos tâches quotidiennes en espérant qu’elle soit intéressante. On se plaint parfois de ne pas trouver de sens à ce qu’on fait ; eh bien voilà !</p><p><strong>Un petit message de notre équipe marketing Data Bene :</strong> Notre équipe d’ingénieurs PostgreSQL expérimentés peut vous aider à améliorer votre efficacité énergétique, à optimiser vos bases de données et à adopter des pratiques de codage responsables. Vous bénéficierez ainsi d’avantages directs : des opérations de base de données plus rapides, une consommation de ressources réduite, des coûts moindres et un impact environnemental moindre. Curieux d’en savoir plus sur nos services ? <a href=\"https://data-bene.io/en/#contact\" rel=\"noopener\">Contactez-nous ! Nous serions ravis d’en discuter.</a></p></body></html>\n",
      "date_published": "2026-01-19T00:00:00Z"
    }
    ,{
      "id": "https://www.data-bene.io/fr/blog/open-source-experience-2025/",
      "url": "https://www.data-bene.io/fr/blog/open-source-experience-2025/",
      "title": "Open Source Experience 2025",
      "content_html": "\n<html><head></head><body><p>L’édition 2025 de l’<a href=\"https://www.opensource-experience.com/\" rel=\"noopener\">Open Source Experience (OSXP)</a> s’est tenue les 10 et 11 décembre sous le thème « Open Source, clé de l’autonomie stratégique de l’Europe ». L’accent portait, comme vous l’imaginez, entièrement sur la redéfinition de l’avenir numérique européen comme étant mené par les innovations open source à travers toutes les technologies (incluant la gestion des données, le cloud et la cybersécurité). Cette année, de nombreuses conférences se sont largement concentrées sur l’intersection entre l’open source et les technologies d’IA (en accord avec l’accent que l’industrie technologique a mis sur l’IA en général, en 2025).</p><h2 id=\"levenement\"><a href=\"https://www.data-bene.io/fr/blog/open-source-experience-2025/#levenement\" class=\"heading-anchor\">L’événement</a></h2><p>L’événement a duré 2 jours avec 90 exposants, 130 sessions, 150 intervenants et plus de 4 000 participants - une conférence de très grande envergure, située à la Cité des Sciences et de l’Industrie à Paris.</p><p>Ce lieu particulier était plus petit que celui de l’année dernière (Le Palais des Congrès) et les salles dans lesquelles nous sommes allés étaient toutes pleines en raison de leur petite taille (environ 20 ou 30 places tout au plus).</p><h2 id=\"le-format-des-conferences\"><a href=\"https://www.data-bene.io/fr/blog/open-source-experience-2025/#le-format-des-conferences\" class=\"heading-anchor\">Le format des conférences</a></h2><p>Les présentations ont été données en anglais et en français. Fait intéressant, il n’y avait pas de “salles silencieuses” cette année (où des écouteurs sont fournis à chaque participant). Tout le monde n’a pas apprécié ce format l’année dernière, mais c’était utile pour suivre deux conférences, ou basculer entre elles en fonction du contenu ou des questions.</p><p>Deux membres de notre équipe étaient présents et ont pu découvrir divers exposants et salles dédiées aux conférences répartis sur trois étages. Ces dernières duraient 20 minutes et bien que trop courtes pour entrer dans les détails, ce format était intéressant pour découvrir les nouvelles technologies et attiser notre curiosité d’un coup d’œil.</p><h2 id=\"le-contenu-des-conferences\"><a href=\"https://www.data-bene.io/fr/blog/open-source-experience-2025/#le-contenu-des-conferences\" class=\"heading-anchor\">Le contenu des conférences</a></h2><p>Il y avait six pistes dans lesquelles les conférences étaient catégorisées :</p><ul class=\"list\"><li>Modèles économiques et gouvernance pour des stratégies ouvertes durables</li><li>Intelligence artificielle et calcul scientifique pour l’analyse des données</li><li>Architecture cloud et virtualisation pour un avenir autonome</li><li>Développement - l’innovation logicielle en action</li><li>Cybersécurité et chaîne de production logicielle : l’Open Source comme fondement de confiance</li><li>Outils collaboratifs et applications métier : reprendre l’autonomie numérique</li></ul><p>Nous avons trouvé le sujet des solutions open source dans le secteur public le plus intéressant. En particulier, il était facile de voir que notre dépendance en tant que société mondiale aux cinq grandes entreprises technologiques (GAFAM : Google, Apple, Facebook, Amazon et Microsoft) a considérablement augmenté ces dernières années. Les logiciels open source sont une solution directe pour protéger notre droit collectif à la vie privée à l’ère numérique, ce qui explique exactement pourquoi des conférences comme celle-ci sont si importantes pour la découverte d’alternatives OSS et l’innovation qui conduit à un développement ultérieur dans ce secteur.</p><h2 id=\"la-participation\"><a href=\"https://www.data-bene.io/fr/blog/open-source-experience-2025/#la-participation\" class=\"heading-anchor\">La participation</a></h2><p>La fréquentation a été particulièrement importante dès le premier jour. Nous avons été ravis d’avoir l’occasion d’échanger en “présentiel”, et de rencontrer nos partenaires, en particulier <a href=\"https://www.ow2.org/\" rel=\"noopener\">OW2</a> qui organise également un évènement Open Source, annuel, en Juin. (L’appel à conférence est ouvert jusqu’au 14 février 2026 - consultez l’appel à propositions d’OW2Con’26 <a href=\"https://www.ow2con.org/view/2026/Call_For_Presentations\" rel=\"noopener\">ici</a>.)</p><p>L’évènement étant entièrement sur les technologies open source, nous avons pu discuter avec les nombreux participants de sujets tels que le support PostgreSQL, les difficultés et impacts organisationnel pour les entreprises souhaitant innover et adopter PostgreSQL, avec en trame de fond la demande du marché pour se libérer des contraintes de licence des éditeurs logiciels.</p><p>Nous avons également eu le plaisir de rencontrer des acteurs de l’innovation “hardware” open-source, en résonnance avec notre propre R&amp;D sur les processeurs RISC-V.</p><p>De nombreux projets libres et open source étaient représentés. Quelques exemples incluent <a href=\"https://nextcloud.com\" rel=\"noopener\">Nextcloud</a> (une plateforme de collaboration cloud auto-hébergée que nous utilisons personnellement pour l’hébergement ici chez Data Bene), qui est une alternative à Nextcloud), et <a href=\"https://opentalk.eu/en\" rel=\"noopener\">OpenTalk</a>, une solution de visioconférence conforme au RGPD, opérant dans des centres de données allemands.</p><h2 id=\"en-conclusion\"><a href=\"https://www.data-bene.io/fr/blog/open-source-experience-2025/#en-conclusion\" class=\"heading-anchor\">En conclusion</a></h2><p>L’événement était réussi et bien organisé. La seule chose qui aurait amélioré l’expérience aurait été des présentations plus longues pour explorer les divers sujets abordés plus en profondeur. Si vous souhaitez découvrir de nouveaux projets open source, notez que l’événement est également une très bonne opportunité pour échanger en toute liberté sur ces sujets.</p><p>Les rediffusions vidéo pour 2025 n’ont pas encore été publiées, mais les enregistrements des conférences passées peuvent être trouvés sur le <a href=\"https://www.opensource-experience.com/en/video-replays\" rel=\"noopener\">site officiel, ici</a>.</p><p>Dans l’ensemble, nous avons beaucoup apprécié l’événement et espérons y assister l’année prochaine !</p></body></html>\n",
      "date_published": "2026-01-03T00:00:00Z"
    }
    ,{
      "id": "https://www.data-bene.io/fr/blog/postgres-ibiza-2025/",
      "url": "https://www.data-bene.io/fr/blog/postgres-ibiza-2025/",
      "title": "PGIBZ 2025 : un événement pour la communauté Postgres à Ibiza",
      "content_html": "\n<html><head></head><body><p><a href=\"https://pgibz.io/\" rel=\"noopener\">Postgres Ibiza (PGIBZ)</a> : une conférence open source conçue pour rassembler des personnes passionnées par PostgreSQL à Ibiza, un lieu détendu propice à des discussions fraîches et innovantes. Un événement international organisé par l’association à but non lucratif PostgreSQL España.</p><p>C’était la première fois que l’équipe Data Bene assistait à cet événement, et nous sommes heureux de partager qu’il s’est avéré très positif.</p><h2 id=\"la-conference\"><a href=\"https://www.data-bene.io/fr/blog/postgres-ibiza-2025/#la-conference\" class=\"heading-anchor\">La conférence</a></h2><h3 id=\"lieu-et-lieu-de-levenement\"><a href=\"https://www.data-bene.io/fr/blog/postgres-ibiza-2025/#lieu-et-lieu-de-levenement\" class=\"heading-anchor\">Lieu et lieu de l’événement</a></h3><p>Comme son nom l’indique, cette conférence a lieu sur l’île méditerranéenne d’Ibiza. Pour ceux qui le connaissent moins, le site touristique officiel propose <a href=\"https://ibiza.travel/en/know-ibiza/where-we-are/\" rel=\"noopener\">un bon aperçu</a> auquel vous pouvez vous référer. Et il va sans dire que ce <a href=\"https://whc.unesco.org/en/list/417\" rel=\"noopener\">site classé au patrimoine mondial de l’UNESCO</a> offre des attractions incroyables en dehors même de la conférence. Combiné à un potentiel long trajet en avion, il est fortement recommandé de prévoir un jour ou deux supplémentaires (ou plus) pour explorer l’île et profiter de l’expérience locale.</p><p>L’événement lui-même est hébergé au <a href=\"https://www.palaciocongresosibiza.com/ibiza-congress-center/#main_english\" rel=\"noopener\">Palacio de Congresos de Ibiza</a> ; un centre de congrès sur deux niveaux avec de multiples salles et un service de restauration. Bien qu’il soit situé en dehors de la capitale, le lieu est accessible en voiture en un temps raisonnable (~15 minutes). À noter également que le centre est à distance de marche de nombreux hôtels, restaurants et d’une plage ! Nous avons séjourné à l’<a href=\"https://www.hoteltrestorresibiza.com/\" rel=\"noopener\">Hôtel Tres Torres</a>, que nous pouvons recommander, bien que, pour être honnête, il soit difficile de faire un mauvais choix, surtout après un peu de recherche préalable.</p><p>En bref, pour ce qui est des activités annexes, notre recommandation principale serait de visiter la ville d’Ibiza. Vous y trouverez une quantité surprenante de commerces, de restaurants et de visites. Ajoutez à cela une promenade dans le quartier historique et vous avez une expérience plutôt mémorable.</p><h3 id=\"participation\"><a href=\"https://www.data-bene.io/fr/blog/postgres-ibiza-2025/#participation\" class=\"heading-anchor\">Participation</a></h3><p>PGIBZ de cette année a accueilli environ 30 à 40 participants venus du monde entier, dont la Chine et les États-Unis. Et bien qu’il y ait certes deux côtés à la pièce, je considère cette taille de groupe plutôt comme un point positif. En effet, lors des sessions de questions-réponses après les présentations, ainsi que lors des pauses café, j’ai trouvé les interactions globalement plus engageantes. C’était particulièrement vrai lors des rencontres et retrouvailles avec des membres d’entreprises de petite taille ainsi que des entreprises de dimension globale.</p><h2 id=\"presentations-de-notre-equipe\"><a href=\"https://www.data-bene.io/fr/blog/postgres-ibiza-2025/#presentations-de-notre-equipe\" class=\"heading-anchor\">Présentations de notre équipe</a></h2><h3 id=\"catherine\"><a href=\"https://www.data-bene.io/fr/blog/postgres-ibiza-2025/#catherine\" class=\"heading-anchor\">Catherine</a></h3><p>La première des intervenantes Data Bene, et pour la présentation inaugurale de la première journée, était Catherine Bouxin. Sa présentation traitait de l’impact environnemental de la technologie et reflétait la philosophie selon laquelle les sujets importants ne sont pas toujours ceux dont on parle, et qu’ils ne sont souvent même pas considérés comme un problème ! En effet, Catherine a cadré cette conversation principalement comme un rappel de la responsabilité que nous partageons en tant que membres de la communauté PostgreSQL. De nombreuses inventions passionnantes ont vu le jour récemment, certaines avec des implications de transformation de la société, mais nous ne pouvons ignorer l’intensité des ressources que beaucoup d’entre elles nécessitent.</p><p>Nous souscrivons pleinement au message de Catherine sur la contribution à un avenir plus vert et la prise de décisions réfléchies à cette fin, et nous sommes ravis que cela ait été très bien accueilli par le public.</p><h3 id=\"cedric\"><a href=\"https://www.data-bene.io/fr/blog/postgres-ibiza-2025/#cedric\" class=\"heading-anchor\">Cédric</a></h3><p>Le deuxième jour, notre fondateur et PDG, Cédric Villemain, a présenté les points forts statistiques de la grande version 18 de PostgreSQL (<a href=\"https://www.postgresql.org/docs/release/18.0/\" rel=\"noopener\">notes officielles liées ici</a>). (Après l’événement, il a créé un billet de blog sur le sujet des statistiques cumulées dans Postgres 18 — <a href=\"https://www.data-bene.io/en/blog/cumulative-statistics-in-postgresql-18/\" rel=\"noopener\">voir ici</a> !) Notre équipe chez Data Bene est fan des statistiques et de la mise en évidence des données, ce qui nous a amenés à créer l’extension PostgreSQL <a href=\"https://codeberg.org/Data-Bene/StatsMgr\" rel=\"noopener\">StatsMgr</a>. <em>Si vous avez raté les informations sur StatsMgr et souhaitez en savoir plus, <a href=\"https://www.data-bene.io/en/blog/postgres-cafe-expand-monitoring-capabilities-with-statsmgr/\" rel=\"noopener\">consultez notre précédent billet de blog et l’épisode de Postgres Café sur le sujet.</a></em></p><h3 id=\"evan\"><a href=\"https://www.data-bene.io/fr/blog/postgres-ibiza-2025/#evan\" class=\"heading-anchor\">Evan</a></h3><p>Immédiatement après Cédric, j’ai eu l’opportunité de présenter le développement et la maintenance d’une extension PostgreSQL basée sur Rust (encore au stade très précoce) qui aide à faciliter la transition d’Oracle vers PostgreSQL. Ce projet, nommé <code>pgtap_gen</code>, s’appuie sur le projet existant <a href=\"https://github.com/theory/pgtap\" rel=\"noopener\">pgTAP</a> pour automatiser la création de tests unitaires sur IvorySQL (un PostgreSQL forké à 100 % open source avec des composants analogues à Oracle). J’ai trouvé très encourageant de recevoir les réactions et retours du public. De plus, c’est gratifiant de participer à l’écosystème PostgreSQL, même pour des initiatives de preuve de concept !</p><h3 id=\"frederic\"><a href=\"https://www.data-bene.io/fr/blog/postgres-ibiza-2025/#frederic\" class=\"heading-anchor\">Frédéric</a></h3><p>Vers la fin du deuxième jour, Frédéric a prononcé un discours sur les niveaux d’isolation des transactions dans PostgreSQL (que vous aurez peut-être la chance de voir plus tard, car il a soumis la même présentation à pgDay Paris 2026 et PGDay CERN 2026 !). Il a exploré chaque niveau d’isolation de Postgres avec des exemples pratiques, et a expliqué comment tout fonctionne en coulisses pour définir des étapes concrètes permettant de choisir en toute confiance le bon niveau pour le bon contexte. Les participants ont semblé trouver la présentation intéressante et instructive, nous pourrions donc voir d’autres contenus sur ce sujet et des sujets similaires pour aider ceux qui ont raté l’opportunité d’apprendre sur ce thème.</p><h2 id=\"conclusions\"><a href=\"https://www.data-bene.io/fr/blog/postgres-ibiza-2025/#conclusions\" class=\"heading-anchor\">Conclusions</a></h2><p>Nous avons choisi de sponsoriser et d’assister à PGIBZ 2025 car nous croyons qu’il est important de promouvoir la communauté PostgreSQL dans le monde. Quoi qu’il en soit, c’est un événement qui cherche à améliorer l’éducation autour de Postgres. Les bénéfices de l’événement sont utilisés par l’organisation parente à but non lucratif, PostgreSQL España, pour financer la traduction de la documentation officielle PostgreSQL en espagnol.</p><p>Des approfondissements détaillés sur chacun des sujets de présentation mentionnés ci-dessus sont en cours ; n’hésitez pas à nous suivre sur <a href=\"https://www.linkedin.com/company/91744288/\" rel=\"noopener\">LinkedIn</a> et <a href=\"https://fosstodon.org/@data_bene\" rel=\"noopener\">Mastodon</a> pour les repérer quand ils seront publiés sur notre blog.</p><p>Nous avons beaucoup apprécié notre temps passé à PGIBZ 2025, et sommes honorés d’avoir eu l’opportunité de présenter et de participer. Hâte de revenir l’année prochaine !</p><h2 id=\"references\"><a href=\"https://www.data-bene.io/fr/blog/postgres-ibiza-2025/#references\" class=\"heading-anchor\">Références</a></h2><ul class=\"list\"><li><a href=\"https://ibiza.travel/en/know-ibiza/where-we-are/\" rel=\"noopener\">https://ibiza.travel/en/know-ibiza/where-we-are/</a></li><li><a href=\"https://pgibz.io/\" rel=\"noopener\">https://pgibz.io/</a></li><li><a href=\"https://whc.unesco.org/en/list/417\" rel=\"noopener\">https://whc.unesco.org/en/list/417</a></li><li><a href=\"https://www.hoteltrestorresibiza.com/\" rel=\"noopener\">https://www.hoteltrestorresibiza.com/</a></li></ul></body></html>\n",
      "date_published": "2025-12-11T00:00:00Z"
    }
    ,{
      "id": "https://www.data-bene.io/fr/blog/transitionnez-facilement-vers-postgresql-depuis-oracle/",
      "url": "https://www.data-bene.io/fr/blog/transitionnez-facilement-vers-postgresql-depuis-oracle/",
      "title": "Transitionnez facilement vers PostgreSQL depuis Oracle",
      "content_html": "\n<html><head></head><body><p>Si vous avez besoin de transition rapidement d’Oracle vers PostgreSQL, sans vous préoccuper des conversions de types ou autres packages Oracle qui nécessitent des modifications pour être compatible PostgreSQL, une solution utile est IvorySQL !</p><h2 id=\"introduction\"><a href=\"https://www.data-bene.io/fr/blog/transitionnez-facilement-vers-postgresql-depuis-oracle/#introduction\" class=\"heading-anchor\">Introduction</a></h2><p>De plus en plus d’entreprises cherchent à se libérer des coûts et des contraintes d’Oracle en migrant vers PostgreSQL. Mais comment réussir cette transition sans y passer des mois ? Voici une méthode éprouvée, rapide et sécurisée, basée sur des retours d’expérience et des outils open source.</p><h3 id=\"commencer-par-evaluer-et-cartographier\"><a href=\"https://www.data-bene.io/fr/blog/transitionnez-facilement-vers-postgresql-depuis-oracle/#commencer-par-evaluer-et-cartographier\" class=\"heading-anchor\">Commencer par évaluer et cartographier</a></h3><p>Avant de migrer, il est essentiel de faire l’état des lieux : lister les objets Oracle par une extraction complète (tables, vues, séquences, procédures, fonctions, packages).</p><p>Mais aussi avoir des échanges réguliers avec le client pour affiner les constats et valider les orientations, mais aussi d’identifier les dépendances (applications connectées avec quelle technologie, jobs, interfaces,…)</p><p>Et enfin, repérer les spécificités Oracle du client (fonctions spécifiques comme ROWID, DUAL, DBMS_XXX,…) et tout autre mot-clé demandant une attention particulière.</p><h3 id=\"choisir-les-bons-outils-open-source\"><a href=\"https://www.data-bene.io/fr/blog/transitionnez-facilement-vers-postgresql-depuis-oracle/#choisir-les-bons-outils-open-source\" class=\"heading-anchor\">Choisir les bons outils open source</a></h3><p>La réussite d’une transition vers PostgreSQL - car il s’agit bien d’une transition progressive et non d’une migration - repose autant sur la stratégie que sur les outils.</p><p>Il ne suffit pas de copier des objets : il faut comprendre les subtilités du moteur Oracle et les transposer intelligemment dans l’univers PostgreSQL.</p><p>Parmi les outils incontournables, Ora2Pg joue un rôle central. Il permet non seulement de générer des rapports d’inventaire clairs, mais aussi d’automatiser la conversion des schémas, des données et du code PL/SQL. C’est un accélérateur précieux pour les projets bien structurés.</p><p>Mais dans certains contextes, la réalité est plus complexe. De nombreux clients accumulent une dette technique importante, avec des milliers de lignes de code procédural. Tenter de tout réécrire en PL/pgSQL dans un délai court reviendrait à épuiser les équipes, tout en compromettant la migration elle-même. Maintenir deux bases de code — l’une en PL/SQL, l’autre en PL/pgSQL — pendant une phase de transition complète est souvent intenable sur le plan organisationnel.</p><p>C’est précisément là qu’IvorySQL offre une alternative puissante. Ce fork de PostgreSQL, enrichi de compatibilités Oracle (PL/SQL, ROWID, DUAL, etc.), permet de réduire considérablement le besoin de réécriture immédiate. En combinant IvorySQL avec une documentation ciblée et des scripts de validation métier, on obtient une transition plus rapide, plus fiable, et surtout mieux maîtrisée.</p><p>Une fois en production, les équipes disposent du temps nécessaire pour réécrire progressivement leur code procédural en PL/pgSQL, sans pression ni rupture fonctionnelle.</p><h3 id=\"integration-et-tests\"><a href=\"https://www.data-bene.io/fr/blog/transitionnez-facilement-vers-postgresql-depuis-oracle/#integration-et-tests\" class=\"heading-anchor\">Intégration et tests</a></h3><p>L’un des grands avantages d’IvorySQL, c’est qu’il réalise une partie de l’intégration en amont. Grâce à son support natif du PL/SQL, des objets Oracle et de la syntaxe Oracle-compatible, de nombreux éléments migrés via Ora2Pg fonctionnent immédiatement sans adaptation lourde.</p><p>Cela ne dispense évidemment pas d’une phase de test, bien au contraire : il est essentiel de valider les comportements métier dans un environnement de préproduction IvorySQL. Les procédures, fonctions, packages, triggers et vues doivent être testés avec des cas réels, en comparant les résultats entre Oracle et IvorySQL pour garantir l’équivalence fonctionnelle.</p><p>Des scripts de comparaison peuvent être utilisés pour vérifier les réponses aux requêtes, les effets des transactions, ou les comportements des fonctions migrées. Mais dans bien des cas, IvorySQL permet de réduire considérablement le besoin de patchs ou de réécriture, ce qui accélère la mise en production et sécurise la transition.</p><h3 id=\"documenter-et-accompagner\"><a href=\"https://www.data-bene.io/fr/blog/transitionnez-facilement-vers-postgresql-depuis-oracle/#documenter-et-accompagner\" class=\"heading-anchor\">Documenter et accompagner</a></h3><p>Une transition réussie ne se limite pas à la technique : elle repose aussi sur une documentation claire et un accompagnement adapté. Il est essentiel de rédiger des cahiers de tests entiers et exhaustifs par objet complexe et modules (procédure, package, trigger…), afin de garder une trace des choix techniques, des adaptations réalisées, et des points d’attention.</p><p>L’accompagnement des équipes client est tout aussi important. Des ateliers ciblés permettent de transmettre les bonnes pratiques, d’expliquer les différences entre Oracle et PostgreSQL, et de faciliter la prise en main d’IvorySQL.</p><p>Enfin, la réussite d’une transition vers PostgreSQL repose aussi sur l’accompagnement des équipes techniques et fonctionnelles. Des sessions de formation ciblées permettent aux développeurs, DBA et chefs de projet de s’approprier les spécificités d’IvorySQL, de comprendre les différences avec Oracle, et de monter en compétence rapidement.</p><p>Ce dispositif s’appuie également sur un support technique structuré, qui aide à résoudre les blocages, à sécuriser les choix d’implémentation, et à fluidifier les échanges entre les équipes projet et les experts migration.</p><h2 id=\"ivorysql-dans-le-monde-reel\"><a href=\"https://www.data-bene.io/fr/blog/transitionnez-facilement-vers-postgresql-depuis-oracle/#ivorysql-dans-le-monde-reel\" class=\"heading-anchor\">IvorySQL dans le monde réel</a></h2><p>Lors d’une mission récente pour une entreprise du secteur privé, nous avons accompagné la transition d’une base Oracle vers IvorySQL dans un contexte contraint : dette technique importante, volumétrie élevée, et délais serrés.</p><p>Grâce à IvorySQL et notre capacité à automatiser cette transition, cette transition s’est faite rapidement et la quasi totalité des objets ont été intégrés sans réécriture.</p><p>La bascule d’IvorySQL vers PostgreSQL peut s’effectuer sereinement, dans la mesure où l’application fonctionne pleinement et répond aux attentes métier.</p><p>Les équipes ont pu se concentrer sur les tests métier, tandis que la formation ciblée et le support technique ont permis une montée en compétence rapide.</p><p>Il est indispensable de réussir ce genre de projet pour emmagasiner de la confiance et développer cette opération sur la totalité de votre parc d’instances Oracle !</p><p>Vous envisagez une transition Oracle vers PostgreSQL ? Parlons-en.</p><p>Contactez notre équipe d’experts, à tout moment: <a href=\"mailto:contact@data-bene.io\">contact@data-bene.io</a></p><p>Le 26 novembre 2025, IvorySQL 5.0 a été publié - <a href=\"https://www.postgresql.org/about/news/ivorysql-50-released-major-oracle-compatibility-expansion-on-postgresql-180-foundation-3180/\" rel=\"noopener\">voir l’annonce ici</a> pour plus d’informations sur ce projet open source.</p></body></html>\n",
      "date_published": "2025-12-10T00:00:00Z"
    }
    ,{
      "id": "https://www.data-bene.io/fr/blog/le-saviez-vous-les-tables-dans-postgresql-sont-limitees-a-1600-colonnes/",
      "url": "https://www.data-bene.io/fr/blog/le-saviez-vous-les-tables-dans-postgresql-sont-limitees-a-1600-colonnes/",
      "title": "Le saviez-vous ? Les tables dans PostgreSQL sont limitées à 1600 colonnes",
      "content_html": "\n<html><head></head><body><p><strong>Saviez-vous qu’une table ne peut pas contenir plus de 1 600 colonnes ?</strong> Cet article de blog est inspiré d’une conversation avec Pierre Ducroquet.</p><h2 id=\"tout-dabord-la-documentation\"><a href=\"https://www.data-bene.io/fr/blog/le-saviez-vous-les-tables-dans-postgresql-sont-limitees-a-1600-colonnes/#tout-dabord-la-documentation\" class=\"heading-anchor\">Tout d’abord, la documentation</a></h2><p><a href=\"https://www.postgresql.org/docs/current/limits.html\" rel=\"noopener\">L’annexe K</a> de la documentation PostgreSQL indique qu’une table peut contenir jusqu’à 1 600 colonnes.</p><p>Il s’agit d’une <strong>limite codée en dur</strong>, visible dans le code source à l’adresse <code>src/include/access/htup_details.h</code> :</p><pre class=\"language-plaintext\"><code class=\"language-plaintext\">#define MaxTupleAttributeNumber 1664\n#define MaxHeapAttributeNumber\t1600</code></pre><h2 id=\"atteindre-la-limite-de-maniere-classique\"><a href=\"https://www.data-bene.io/fr/blog/le-saviez-vous-les-tables-dans-postgresql-sont-limitees-a-1600-colonnes/#atteindre-la-limite-de-maniere-classique\" class=\"heading-anchor\">Atteindre la limite de manière classique</a></h2><p>Vérifions d’abord cette affirmation par quelques tests.</p><h3 id=\"jouer-avec-la-definition-de-la-table\"><a href=\"https://www.data-bene.io/fr/blog/le-saviez-vous-les-tables-dans-postgresql-sont-limitees-a-1600-colonnes/#jouer-avec-la-definition-de-la-table\" class=\"heading-anchor\">Jouer avec la définition de la table</a></h3><p>Nous utilisons ici un script bash simple, facile à adapter aux différents tests.</p><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token comment\">-- Exemple classique</span>\n\n<span class=\"token keyword\">DO</span> $$\n<span class=\"token keyword\">DECLARE</span>\n    i <span class=\"token keyword\">int</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">BEGIN</span>\n    <span class=\"token keyword\">EXECUTE</span> <span class=\"token string\">'DROP TABLE IF EXISTS tint_1601;'</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">EXECUTE</span> <span class=\"token string\">'CREATE TABLE tint_1601(i_1 int);'</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">FOR</span> i <span class=\"token operator\">IN</span> <span class=\"token number\">2.</span><span class=\"token number\">.1601</span> <span class=\"token keyword\">LOOP</span>\n        <span class=\"token keyword\">EXECUTE</span> <span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">'ALTER TABLE tint_1601 ADD COLUMN i_%s int;'</span><span class=\"token punctuation\">,</span> i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">END</span> <span class=\"token keyword\">LOOP</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">END</span> $$<span class=\"token punctuation\">;</span></code></pre><p>Le résultat est le suivant :</p><pre class=\"language-plaintext\"><code class=\"language-plaintext\">NOTICE:  table \"tint_1600\" does not exist, skipping\nERROR:  tables can have at most 1600 columns\nCONTEXT:  SQL statement \"ALTER TABLE tint_1600 ADD COLUMN i_1601 int;\"\nPL/pgSQL function inline_code_block line 8 at EXECUTE</code></pre><p>Jusqu’ici, tout va bien (ou du moins, tout fonctionne comme prévu).</p><p>Vous pourriez tenter de remplacer le type <code>int4</code> par le type <code>int2</code> pour arriver à créer une table de plus de 1 600 colonnes. Mais cela ne fonctionnera pas plus, car il s’agit d’une limite codée en dur.</p><h3 id=\"jouer-avec-le-contenu-dune-table\"><a href=\"https://www.data-bene.io/fr/blog/le-saviez-vous-les-tables-dans-postgresql-sont-limitees-a-1600-colonnes/#jouer-avec-le-contenu-dune-table\" class=\"heading-anchor\">Jouer avec le contenu d’une table</a></h3><p>Générons une table de 1600 colonnes à partir du script sql précédent :</p><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token keyword\">DO</span> $$\n<span class=\"token keyword\">DECLARE</span>\n    i <span class=\"token keyword\">int</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">BEGIN</span>\n    <span class=\"token keyword\">EXECUTE</span> <span class=\"token string\">'DROP TABLE IF EXISTS tint_1600;'</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">EXECUTE</span> <span class=\"token string\">'CREATE TABLE tint_1600(i_1 int);'</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">FOR</span> i <span class=\"token operator\">IN</span> <span class=\"token number\">2.</span><span class=\"token number\">.1600</span> <span class=\"token keyword\">LOOP</span>\n        <span class=\"token keyword\">EXECUTE</span> <span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">'ALTER TABLE tint_1600 ADD COLUMN i_%s int;'</span><span class=\"token punctuation\">,</span> i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">END</span> <span class=\"token keyword\">LOOP</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">END</span> $$<span class=\"token punctuation\">;</span></code></pre><p>Construisons puis insérons un tuple de 1600 colonnes :</p><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token keyword\">DO</span> $$\n<span class=\"token keyword\">DECLARE</span>\n    s <span class=\"token keyword\">TEXT</span><span class=\"token punctuation\">;</span>\n    rows_inserted <span class=\"token keyword\">int</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">BEGIN</span>\n    s :<span class=\"token operator\">=</span> <span class=\"token function\">format</span><span class=\"token punctuation\">(</span>\n                 <span class=\"token string\">'INSERT INTO tint_1600 VALUES (1%s);'</span>\n               <span class=\"token punctuation\">,</span> <span class=\"token keyword\">repeat</span><span class=\"token punctuation\">(</span> <span class=\"token string\">',1'</span> <span class=\"token punctuation\">,</span> <span class=\"token number\">1599</span> <span class=\"token punctuation\">)</span>\n               <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">EXECUTE</span> s<span class=\"token punctuation\">;</span>\n\n    GET DIAGNOSTICS rows_inserted <span class=\"token operator\">=</span> ROW_COUNT<span class=\"token punctuation\">;</span>\n    RAISE NOTICE <span class=\"token string\">'Rows inserted: %'</span><span class=\"token punctuation\">,</span> rows_inserted<span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">END</span> $$<span class=\"token punctuation\">;</span></code></pre><p>The output is:</p><pre class=\"language-plaintext\"><code class=\"language-plaintext\">NOTICE:  Rows inserted: 1\nDO</code></pre><p>Sans surprise, c’est encore un succès.</p><h3 id=\"trop-gros-pour-echouer\"><a href=\"https://www.data-bene.io/fr/blog/le-saviez-vous-les-tables-dans-postgresql-sont-limitees-a-1600-colonnes/#trop-gros-pour-echouer\" class=\"heading-anchor\">Trop gros pour échouer ?</a></h3><p>Continuons à repousser les limites.</p><p>On créé maintenant une autre table de 1 600 colonnes, cette fois avec le type de données <code>char(127)</code>.</p><p>On réutilise notre script bash avec quelques modifications :</p><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token comment\">-- Create a table with 1,600 columns: 1 x int + 1599 x char(127)</span>\n<span class=\"token keyword\">DO</span> $$\n<span class=\"token keyword\">DECLARE</span>\n    i <span class=\"token keyword\">int</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">BEGIN</span>\n    <span class=\"token keyword\">EXECUTE</span> <span class=\"token string\">'DROP TABLE IF EXISTS tint_1600;'</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">EXECUTE</span> <span class=\"token string\">'CREATE TABLE tint_1600(i_1 int);'</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">FOR</span> i <span class=\"token operator\">IN</span> <span class=\"token number\">2.</span><span class=\"token number\">.1600</span> <span class=\"token keyword\">LOOP</span>\n        <span class=\"token keyword\">EXECUTE</span> <span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">'ALTER TABLE tint_1600 ADD COLUMN c_%s char(127) NOT NULL;'</span><span class=\"token punctuation\">,</span> i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">END</span> <span class=\"token keyword\">LOOP</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">END</span> $$<span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">-- Insert a tuple - 1 x int + 1599 x char(127)</span>\n<span class=\"token keyword\">DO</span> $$\n<span class=\"token keyword\">DECLARE</span>\n    s <span class=\"token keyword\">TEXT</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">BEGIN</span>\n    s :<span class=\"token operator\">=</span> <span class=\"token function\">format</span><span class=\"token punctuation\">(</span>\n                 <span class=\"token string\">'INSERT INTO tint_1600 VALUES (1%s);'</span>\n               <span class=\"token punctuation\">,</span> <span class=\"token keyword\">repeat</span><span class=\"token punctuation\">(</span> $q$<span class=\"token punctuation\">,</span><span class=\"token string\">'1'</span>::<span class=\"token keyword\">char</span><span class=\"token punctuation\">(</span><span class=\"token number\">127</span><span class=\"token punctuation\">)</span>$q$ <span class=\"token punctuation\">,</span> <span class=\"token number\">1599</span> <span class=\"token punctuation\">)</span>\n               <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">EXECUTE</span> s<span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">END</span> $$<span class=\"token punctuation\">;</span><span class=\"token identifier\"><span class=\"token punctuation\">`</span><span class=\"token punctuation\">`</span></span><span class=\"token punctuation\">`</span>\n\nLe résultat est :</code></pre><p>ERROR: row is too big: size 25616, maximum size 8160</p><pre class=\"language-plaintext\"><code class=\"language-plaintext\">\nComme on peut le voir, la table comporte effectivement 1 600 colonnes, mais cette fois, le tuple ne peut pas tenir dans une seule page heap, ce qui explique l'erreur « row is too big: size 25616, maximum size 8160 ». Si vous avez fait attention au script, vous avez pu constater que les colonnes sont définies comme `NOT NULL`. Aussi, lors de la création de la table, PostgreSQL aurait pu se rendre compte que l'insertion de données serait impossible. Mais il n'y a pas eu d'alerte.\n\n## Quid des JOINs ?\n\nPour simplifier, testons avec une jointure automatique :\n\n```sql\nSELECT a.*,b.* FROM tint_1600 a, tint_1600 b;\nERROR:  target lists can have at most 1664 entries</code></pre><p>Maintenant, c’est la clause <code>SELECT</code> de (<code>a.*,b.*</code>) qui a atteint sa propre limite (<code>MaxTupleAttributeNumber = 1664</code>).</p><h2 id=\"atteindre-la-limite-de-colonnes-de-maniere-inattendue\"><a href=\"https://www.data-bene.io/fr/blog/le-saviez-vous-les-tables-dans-postgresql-sont-limitees-a-1600-colonnes/#atteindre-la-limite-de-colonnes-de-maniere-inattendue\" class=\"heading-anchor\">Atteindre la limite de colonnes de manière inattendue</a></h2><p>Il arrive que vous deviez modifier votre application, et que cela entraîne des modifications de schéma.<br>La plupart du temps, il s’agit de modifications de tables, comme l’ajout ou la suppression de colonnes.</p><h3 id=\"explorer-add-/-drop-column\"><a href=\"https://www.data-bene.io/fr/blog/le-saviez-vous-les-tables-dans-postgresql-sont-limitees-a-1600-colonnes/#explorer-add-/-drop-column\" class=\"heading-anchor\">Explorer <code>ADD</code> / <code>DROP COLUMN</code></a></h3><p>Voyons ce qui se passe côté SQL lorsque nous ajoutons, puis supprimons, une colonne.</p><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token operator\">=</span><span class=\"token comment\"># CREATE TABLE tadc_1600(i_1 int NOT NULL);</span>\n\n<span class=\"token keyword\">CREATE</span> <span class=\"token keyword\">TABLE</span>\n\n<span class=\"token operator\">=</span><span class=\"token comment\"># ALTER TABLE tadc_1600 ADD COLUMN i_2 int NOT NULL;</span>\n\n<span class=\"token keyword\">ALTER</span> <span class=\"token keyword\">TABLE</span>\n\n<span class=\"token operator\">=</span><span class=\"token comment\"># SELECT attname,attnum,attstorage,attnotnull,attisdropped</span>\n   <span class=\"token keyword\">FROM</span> pg_attribute\n   <span class=\"token keyword\">WHERE</span> attrelid<span class=\"token operator\">=</span><span class=\"token punctuation\">(</span>\n                   <span class=\"token keyword\">SELECT</span> oid\n                   <span class=\"token keyword\">FROM</span> pg_class\n                   <span class=\"token keyword\">WHERE</span> relname<span class=\"token operator\">=</span><span class=\"token string\">'tadc_1600'</span>\n                   <span class=\"token punctuation\">)</span>\n     <span class=\"token operator\">AND</span> attnum <span class=\"token operator\">&gt;</span> <span class=\"token number\">0</span> <span class=\"token keyword\">ORDER</span> <span class=\"token keyword\">BY</span> attnum<span class=\"token punctuation\">;</span>\n\n attname <span class=\"token operator\">|</span> attnum <span class=\"token operator\">|</span> attstorage <span class=\"token operator\">|</span> attnotnull <span class=\"token operator\">|</span> attisdropped\n<span class=\"token comment\">---------+--------+------------+------------+--------------</span>\n i_1     <span class=\"token operator\">|</span>      <span class=\"token number\">1</span> <span class=\"token operator\">|</span> p          <span class=\"token operator\">|</span> t          <span class=\"token operator\">|</span> f\n i_2     <span class=\"token operator\">|</span>      <span class=\"token number\">2</span> <span class=\"token operator\">|</span> p          <span class=\"token operator\">|</span> t          <span class=\"token operator\">|</span> f\n<span class=\"token punctuation\">(</span><span class=\"token number\">2</span> <span class=\"token keyword\">rows</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token operator\">=</span><span class=\"token comment\"># ALTER TABLE tadc_1600 DROP COLUMN i_2;</span>\n\n<span class=\"token keyword\">ALTER</span> <span class=\"token keyword\">TABLE</span>\n\n<span class=\"token operator\">=</span><span class=\"token comment\"># SELECT attname,attnum,attstorage,attnotnull,attisdropped</span>\n   <span class=\"token keyword\">FROM</span> pg_attribute\n   <span class=\"token keyword\">WHERE</span> attrelid<span class=\"token operator\">=</span><span class=\"token punctuation\">(</span>\n                   <span class=\"token keyword\">SELECT</span> oid\n                   <span class=\"token keyword\">FROM</span> pg_class\n                   <span class=\"token keyword\">WHERE</span> relname<span class=\"token operator\">=</span><span class=\"token string\">'tadc_1600'</span>\n                   <span class=\"token punctuation\">)</span>\n     <span class=\"token operator\">AND</span> attnum <span class=\"token operator\">&gt;</span> <span class=\"token number\">0</span> <span class=\"token keyword\">ORDER</span> <span class=\"token keyword\">BY</span> attnum<span class=\"token punctuation\">;</span>\n\n           attname            <span class=\"token operator\">|</span> attnum <span class=\"token operator\">|</span> attstorage <span class=\"token operator\">|</span> attnotnull <span class=\"token operator\">|</span> attisdropped\n<span class=\"token comment\">------------------------------+--------+------------+------------+--------------</span>\n i_1                          <span class=\"token operator\">|</span>      <span class=\"token number\">1</span> <span class=\"token operator\">|</span> p          <span class=\"token operator\">|</span> t          <span class=\"token operator\">|</span> f\n <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span>pg<span class=\"token punctuation\">.</span>dropped<span class=\"token punctuation\">.</span><span class=\"token number\">2.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span> <span class=\"token operator\">|</span>      <span class=\"token number\">2</span> <span class=\"token operator\">|</span> p          <span class=\"token operator\">|</span> f          <span class=\"token operator\">|</span> t\n<span class=\"token punctuation\">(</span><span class=\"token number\">2</span> <span class=\"token keyword\">rows</span><span class=\"token punctuation\">)</span></code></pre><p>Lors de la suppression d’une colonne, cette colonne</p><ul class=\"list\"><li>est renommée en « . » + « pg.dropped.» + attnum + « . »,</li><li>devient NULLable,</li><li>est marquée comme supprimée.</li></ul><h3 id=\"iterer-sur-lajout/la-suppression-de-colonnes\"><a href=\"https://www.data-bene.io/fr/blog/le-saviez-vous-les-tables-dans-postgresql-sont-limitees-a-1600-colonnes/#iterer-sur-lajout/la-suppression-de-colonnes\" class=\"heading-anchor\">Itérer sur l’ajout/la suppression de colonnes</a></h3><p>On peut se demander s’il existe une limite au nombre d’opérations d’ajout/suppression qui peuvent être exécutées sur une table donnée.</p><p>Comme d’habitude, testons :</p><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token comment\">-- ADD / DROP COLUMN example</span>\n<span class=\"token keyword\">DO</span> $$\n<span class=\"token keyword\">DECLARE</span>\n    i <span class=\"token keyword\">int</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">BEGIN</span>\n    <span class=\"token keyword\">EXECUTE</span> <span class=\"token string\">'DROP TABLE IF EXISTS tadc;'</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">EXECUTE</span> <span class=\"token string\">'CREATE TABLE tadc(i_1 int);'</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">FOR</span> i <span class=\"token operator\">IN</span> <span class=\"token number\">2.</span><span class=\"token number\">.1601</span> <span class=\"token keyword\">LOOP</span>\n        <span class=\"token keyword\">EXECUTE</span> <span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">'ALTER TABLE tadc ADD COLUMN i_%s int;'</span><span class=\"token punctuation\">,</span> i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">EXECUTE</span> <span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">'ALTER TABLE tadc DROP COLUMN i_%s;'</span><span class=\"token punctuation\">,</span> i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">END</span> <span class=\"token keyword\">LOOP</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">END</span> $$<span class=\"token punctuation\">;</span></code></pre><p>Le résultat est :</p><pre class=\"language-plaintext\"><code class=\"language-plaintext\">ERROR:  tables can have at most 1600 columns\nCONTEXT:  SQL statement \"ALTER TABLE tadc ADD COLUMN i_1601 int;\"\nPL/pgSQL function inline_code_block line 8 at EXECUTE</code></pre><p>Oh oh ! On a atteint la limite des 1 600 ici aussi !</p><p>Explorons un peu ce qui se passe :</p><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token operator\">=</span><span class=\"token comment\"># SELECT attname,attnum,attstorage,attnotnull,attisdropped</span>\n   <span class=\"token keyword\">FROM</span> pg_attribute\n   <span class=\"token keyword\">WHERE</span> attrelid<span class=\"token operator\">=</span><span class=\"token punctuation\">(</span>\n                   <span class=\"token keyword\">SELECT</span> oid\n                   <span class=\"token keyword\">FROM</span> pg_class\n                   <span class=\"token keyword\">WHERE</span> relname<span class=\"token operator\">=</span><span class=\"token string\">'tadc'</span>\n                   <span class=\"token punctuation\">)</span>\n     <span class=\"token operator\">AND</span> attnum <span class=\"token operator\">&gt;</span> <span class=\"token number\">0</span> <span class=\"token keyword\">ORDER</span> <span class=\"token keyword\">BY</span> attnum<span class=\"token punctuation\">;</span>\n\n             attname             <span class=\"token operator\">|</span> attnum <span class=\"token operator\">|</span> attstorage <span class=\"token operator\">|</span> attnotnull <span class=\"token operator\">|</span> attisdropped\n<span class=\"token comment\">---------------------------------+--------+------------+------------+--------------</span>\n i_1                             <span class=\"token operator\">|</span>      <span class=\"token number\">1</span> <span class=\"token operator\">|</span> p          <span class=\"token operator\">|</span> t          <span class=\"token operator\">|</span> f\n <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span>pg<span class=\"token punctuation\">.</span>dropped<span class=\"token punctuation\">.</span><span class=\"token number\">2.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span>    <span class=\"token operator\">|</span>      <span class=\"token number\">2</span> <span class=\"token operator\">|</span> p          <span class=\"token operator\">|</span> f          <span class=\"token operator\">|</span> t\n <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span>pg<span class=\"token punctuation\">.</span>dropped<span class=\"token punctuation\">.</span><span class=\"token number\">3.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span>    <span class=\"token operator\">|</span>      <span class=\"token number\">3</span> <span class=\"token operator\">|</span> p          <span class=\"token operator\">|</span> f          <span class=\"token operator\">|</span> t\n <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span>pg<span class=\"token punctuation\">.</span>dropped<span class=\"token punctuation\">.</span><span class=\"token number\">4.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span>    <span class=\"token operator\">|</span>      <span class=\"token number\">4</span> <span class=\"token operator\">|</span> p          <span class=\"token operator\">|</span> f          <span class=\"token operator\">|</span> t\n <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span>pg<span class=\"token punctuation\">.</span>dropped<span class=\"token punctuation\">.</span><span class=\"token number\">5.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span>    <span class=\"token operator\">|</span>      <span class=\"token number\">5</span> <span class=\"token operator\">|</span> p          <span class=\"token operator\">|</span> f          <span class=\"token operator\">|</span> t\n\n <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span>pg<span class=\"token punctuation\">.</span>dropped<span class=\"token punctuation\">.</span><span class=\"token number\">1599.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span> <span class=\"token operator\">|</span>   <span class=\"token number\">1599</span> <span class=\"token operator\">|</span> p          <span class=\"token operator\">|</span> f          <span class=\"token operator\">|</span> t\n <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span>pg<span class=\"token punctuation\">.</span>dropped<span class=\"token punctuation\">.</span><span class=\"token number\">1600.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span> <span class=\"token operator\">|</span>   <span class=\"token number\">1600</span> <span class=\"token operator\">|</span> p          <span class=\"token operator\">|</span> f          <span class=\"token operator\">|</span> t\n<span class=\"token punctuation\">(</span><span class=\"token number\">1600</span> <span class=\"token keyword\">rows</span><span class=\"token punctuation\">)</span></code></pre><p>La table <code>tadc</code> comporte 1 600 colonnes. Vous pouvez vous en apercevoir car toutes les modifications sont ajoutées à la table, et son contenu n’est pas réécrit.</p><p>Aussi, à ce stade, toute modification supplémentaire visant à ajouter ou supprimer des colonnes sera vouée à l’échec.</p><p>Comment faire pour me sortir de cette situation ?</p><h4 id=\"le-chevalier-du-vacuum-devrait-sauver-la-princesse-postgresql-non\"><a href=\"https://www.data-bene.io/fr/blog/le-saviez-vous-les-tables-dans-postgresql-sont-limitees-a-1600-colonnes/#le-chevalier-du-vacuum-devrait-sauver-la-princesse-postgresql-non\" class=\"heading-anchor\">Le chevalier du VACUUM devrait sauver la princesse PostgreSQL, non ?</a></h4><p>Et non ! La commande <code>VACUUM</code> fonctionne au niveau du tuple, donc même si vous exécutez un <code>VACUUM FULL</code>, la structure de la table ne changera pas.</p><h4 id=\"donc-le-dragon-a-mange-le-chevalier-que-fait-on\"><a href=\"https://www.data-bene.io/fr/blog/le-saviez-vous-les-tables-dans-postgresql-sont-limitees-a-1600-colonnes/#donc-le-dragon-a-mange-le-chevalier-que-fait-on\" class=\"heading-anchor\">Donc le dragon a mangé le chevalier, que fait-on ?</a></h4><p>Il ne s’agit pas d’un problème de tuples morts, mais plutôt d’un problème de catalogue.<br>Vous devez créer une nouvelle définition de table.</p><p>Voici quelques solutions, des plus simples aux plus complexes :</p><ol class=\"list\"><li><p>Créer une nouvelle table avec interruption de service</p><ul class=\"list\"><li><code>CREATE TABLE LIKE (INCLUDING ALL)</code></li><li>Copier (<code>COPY</code>) les données de l’ancienne table vers la nouvelle</li><li>Renommer les tables</li><li>Supprimer l’ancienne table</li></ul></li><li><p>Exploiter la réplication logique pour minimiser les interruptions de service</p><ul class=\"list\"><li><code>CREATE TABLE LIKE (INCLUDING ALL)</code></li><li><code>CREATE local PUBLICATION/SUBSCRIPTION</code></li><li>Une fois les données synchronisées, arrêter/mettre en pause le service applicatif</li><li>Supprimer l’abonnement</li><li>Renommer les tables</li><li>Redémarrer/relancer l’application</li><li>Supprimer l’ancienne table</li></ul></li></ol><h2 id=\"contactez-nous\"><a href=\"https://www.data-bene.io/fr/blog/le-saviez-vous-les-tables-dans-postgresql-sont-limitees-a-1600-colonnes/#contactez-nous\" class=\"heading-anchor\">Contactez-nous</a></h2><p>Vous avez d’autres idées pour résoudre ce problème ? Vous avez trouvé d’autres moyens étranges de déclencher cette erreur liée à la limite codée en dur ? <a href=\"https://www.data-bene.io/en/#contact\" rel=\"noopener\">Contactez-nous</a> ! Nous sommes toujours ravis d’échanger sur PostgreSQL.</p></body></html>\n",
      "date_published": "2025-11-13T00:00:00Z"
    }
    ,{
      "id": "https://www.data-bene.io/fr/blog/statistiques-cumulatives-dans-postgresql-18/",
      "url": "https://www.data-bene.io/fr/blog/statistiques-cumulatives-dans-postgresql-18/",
      "title": "Statistiques cumulatives dans PostgreSQL 18",
      "content_html": "\n<html><head></head><body><p>Dans <strong>PostgreSQL 18</strong>, le sous-système de statistiques et de supervision bénéficie d’une refonte majeure: statistiques cumulatives étendues, nouvelle visibilité I/O par backend, possibilité pour les extensions d’exporter / importer / ajuster les statistiques, et améliorations des contrôles GUC ainsi que du comportement de cache et de snapshot. Ces changements ouvrent de nouvelles perspectives pour l’analyse de performance, la simulation inter-environnements et une meilleure intégration avec les extensions. Dans cet article, j’explore les nouveautés, les points d’attention, les paramètres GUC, ainsi que la manière dont les auteurs d’extensions peuvent exploiter la nouvelle API en C.</p><h2 id=\"introduction-and-motivation\"><a href=\"https://www.data-bene.io/fr/blog/statistiques-cumulatives-dans-postgresql-18/#introduction-and-motivation\" class=\"heading-anchor\">Introduction &amp; motivation</a></h2><p>Les statistiques (au sens large: compteurs de supervision, métriques I/O, et estimations pour le planificateur / optimiseur) sont au cœur à la fois de l’optimisation de performance et des décisions internes de PostgreSQL. Des statistiques transparentes, fiables et manipulables permettent entre autres aux DBAs d’adresser directement l’efficacité de PostgreSQL, et donnent aux «extensions» la possibilité d’améliorer l’expérience utilisateur.</p><p>Cela dit, le système historique de statistiques de PostgreSQL n’était pas exempt de frictions: capacité limitée à réinitialiser les statistiques des relations, métriques exprimées dans des unités pas toujours alignées avec les besoins utilisateurs, absence d’API C pour utiliser le moteur de statistiques cumulatives de PostgreSQL. PostgreSQL 18 répond directement à ces préoccupations.</p><p>Voici un résumé des améliorations clés.</p><h2 id=\"un-avertissement-sur-les-statistiques\"><a href=\"https://www.data-bene.io/fr/blog/statistiques-cumulatives-dans-postgresql-18/#un-avertissement-sur-les-statistiques\" class=\"heading-anchor\">Un avertissement sur les statistiques</a></h2><p>Bien que les statistiques soient extrêmement utiles, leur collecte peut consommer du temps et des ressources. PostgreSQL 18 introduit un point important: avec l’élargissement du spectre des métriques collectables, la taille maximale de la table de hachage a été augmentée. Gardez cela à l’esprit, surtout si vous concevez des systèmes à grande échelle avec des architectures «un ensemble de tables par client»: on a constaté que la limite de 1 Go pouvait être atteinte avec quelques millions de tables.</p><h2 id=\"quoi-de-neuf-dans-postgresql-18-et-les-«-stats-»\"><a href=\"https://www.data-bene.io/fr/blog/statistiques-cumulatives-dans-postgresql-18/#quoi-de-neuf-dans-postgresql-18-et-les-%C2%AB-stats-%C2%BB\" class=\"heading-anchor\">Quoi de neuf dans PostgreSQL 18 et les « stats »</a></h2><p>Voici les nouvelles fonctionnalités majeures ou les améliorations concernant les statistiques et la supervision.</p><p>De manière générale, <a href=\"https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STAT-IO-VIEW\" rel=\"noopener\">pg_stat_io</a> rapporte désormais l’activité I/O en octets plutôt qu’en pages, ce qui est plus pratique pour l’analyse. De plus, les statistiques WAL y ont été déplacées depuis <code>pg_stat_wal</code>, offrant ainsi une vue unique et complète.</p><h3 id=\"mises-a-jour\"><a href=\"https://www.data-bene.io/fr/blog/statistiques-cumulatives-dans-postgresql-18/#mises-a-jour\" class=\"heading-anchor\">Mises à jour</a></h3><p><a href=\"https://www.postgresql.org/docs/18/pgupgrade.html\" rel=\"noopener\">pg_upgrade</a> est désormais capable de conserver les statistiques de l’optimiseur, supprimant la nécessité de relancer un <code>ANALYZE</code> complet pour obtenir de bons plans de requêtes après une montée de version: une avancée très attendue pour les grandes bases!</p><p>Attention toutefois: les statistiques personnalisées ajoutées par une extension ainsi que celles créées avec <a href=\"https://www.postgresql.org/docs/18/sql-createstatistics.html\" rel=\"noopener\">CREATE STATISTICS</a> ne sont pas conservées.</p><p>Vous voudrez sûrement examiner les nouvelles options de <a href=\"https://www.postgresql.org/docs/18/app-vacuumdb.html\" rel=\"noopener\">vacuumdb</a> (<code>--missing-stats-only</code>) pour n’analyser que ce qui est nécessaire.</p><p>Dans la même veine, l’option <code>--[no-]statistics</code> a été ajoutée à <a href=\"https://www.postgresql.org/docs/18/app-pgdump.html\" rel=\"noopener\">pg_dump</a>, <a href=\"https://www.postgresql.org/docs/18/app-pgdumpall.html\" rel=\"noopener\">pg_dumpall</a>, et <a href=\"https://www.postgresql.org/docs/18/app-pgrestore.html\" rel=\"noopener\">pg_restore</a>.</p><h3 id=\"maintenance\"><a href=\"https://www.data-bene.io/fr/blog/statistiques-cumulatives-dans-postgresql-18/#maintenance\" class=\"heading-anchor\">Maintenance</a></h3><p>Il est désormais plus simple d’évaluer l’effort de maintenance sur les objets, puisque le temps total passé dans les opérations VACUUM et ANALYZE (y compris<br>automatiques) est rapporté dans <a href=\"https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STAT-ALL-TABLES-VIEW\" rel=\"noopener\">pg_stat_all_tables</a> et ses variantes.</p><p>Un nouveau GUC à ne pas oublier: <a href=\"https://www.postgresql.org/docs/18/runtime-config-statistics.html#GUC-TRACK-COST-DELAY-TIMING\" rel=\"noopener\">track_cost_delay_timing</a>. Il collecte le temps passé à dormir (suite aux opérations retardées) pour <code>VACUUM</code> et <code>ANALYZE</code>. Très intéressant, mais comme les autres GUC <code>track_io*</code>, il multiplie les appels à l’horloge système, ce qui peut provoquer un impact sévère sur certaines plateformes. Toujours vérifier avec un outil comme <a href=\"https://www.postgresql.org/docs/18/pgtesttiming.html\" rel=\"noopener\">pg_test_timing</a> pour s’assurer que votre système peut le supporter!</p><p>Plus de questions sur l’activité du checkpointer grâce à <a href=\"https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STAT-CHECKPOINTER-VIEW\" rel=\"noopener\">pg_stat_checkpointer</a>. Le nouvel attribut <code>num_done</code> indique le nombre de checkpoints <strong>terminés</strong>. Vous pouvez aussi savoir quel type de buffers a été écrit grâce à <code>slru_written</code>, et <code>buffers_written</code> qui ne concerne désormais que <code>shared_buffers</code>: auparavant, journal et vue n’affichaient pas les mêmes totaux, car un compteur <code>SLRU</code> <a href=\"https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=17cc5f666\" rel=\"noopener\">existait dans un cas mais pas dans l’autre</a>.</p><h3 id=\"analyse\"><a href=\"https://www.data-bene.io/fr/blog/statistiques-cumulatives-dans-postgresql-18/#analyse\" class=\"heading-anchor\">Analyse</a></h3><p>Envie d’en savoir plus sur l’I/O traité par un backend (PID) ? Appelez <a href=\"https://www.postgresql.org/docs/18/monitoring-stats.html#PG-STAT-GET-BACKEND-IO\" rel=\"noopener\">pg_stat_get_backend_io(int)</a> et vous obtiendrez une sortie similaire à la vue <code>pg_stat_io</code>, mais pour ce processus. Pour les stats WAL de ce PID: utilisez <a href=\"https://www.postgresql.org/docs/18/monitoring-stats.html#PG-STAT-GET-BACKEND-WAL\" rel=\"noopener\">pg_stat_get_backend_wal(int)</a>.</p><p>De nouveaux attributs <code>parallel_workers_to_launch</code> et <code>parallel_workers_launched</code> apparaissent dans <a href=\"https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STAT-DATABASE-VIEW\" rel=\"noopener\">pg_stat_database</a>. Le ratio permet de savoir si nous avons assez de slots pour les workers parallèles.</p><p>Changements intéressants dans <a href=\"https://www.postgresql.org/docs/18/pgstatstatements.html\" rel=\"noopener\">pg_stat_statements</a>: plus de requêtes seront regroupées sous le même identifiant. Par exemple, les<br>motifs <code>IN (1,2,3, ...)</code> n’utiliseront que la première et la dernière constante. Un changement plus contre-intuitif concerne le nom de table utilisé dans une requête: seul le nom est pris en compte, pas le schéma ni l’OID de relation. Cela permet de suivre les tables supprimées ou recréées, mais cela peut aussi regrouper les stats de tables sans lien ayant simplement le même nom. Pour séparer les stats de tables homonymes, il faudra les aliaser dans les requêtes (<code>FROM my.table mt, other.table ot</code>)…</p><p>Enfin, ajouts à <a href=\"https://www.postgresql.org/docs/18/view-pg-backend-memory-contexts.html\" rel=\"noopener\">pg_backend_memory_contexts</a> avec <code>path</code> (pour récupérer parent/enfant) et <code>type</code> pour distinguer les contextes <code>AllocSet</code>, <code>Generation</code>, <code>Slab</code> et <code>Bump</code>… Et au fait, que sont <code>Slab</code> et <code>Bump</code> ? Pas documentés ; il faut <a href=\"https://github.com/postgres/postgres/tree/master/src/backend/utils/mmgr\" rel=\"noopener\">lire les en-têtes des fichiers C ici</a>. Ils existent pour optimiser l’allocation, la réallocation et la réinitialisation mémoire selon les usages attendus. Par exemple, <code>Slab</code> est défini comme un «MemoryContext implementation designed for cases where large numbers of equally-sized objects can be allocated and freed efficiently with minimal memory wastage and fragmentation».</p><p>Ah, non, encore une dernière: <code>wal_buffers_full</code> a été ajouté à <code>pg_stat_statements</code> pour permettre un meilleur réglage de <code>wal_buffers</code>.</p><h3 id=\"replication\"><a href=\"https://www.data-bene.io/fr/blog/statistiques-cumulatives-dans-postgresql-18/#replication\" class=\"heading-anchor\">Réplication</a></h3><p>De meilleures informations apparaissent désormais pour la gestion des conflits en réplication logique grâce à de nouveaux attributs dans <a href=\"https://www.postgresql.org/docs/18/monitoring-stats.html#MONITORING-PG-STAT-SUBSCRIPTION-STATS\" rel=\"noopener\">pg_stat_subscription_stats</a>. En référence, cet extrait du <a href=\"https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=6c2b5edec\" rel=\"noopener\">commit</a> liste les attributs introduits:</p><ul class=\"list\"><li><code>confl_insert_exists</code>: nombre de fois où une insertion de ligne a violé une contrainte unique NOT DEFERRABLE.</li><li><code>confl_update_origin_differs</code>: nombre de fois où une mise à jour a été faite sur une ligne déjà modifiée par une autre origine.</li><li><code>confl_update_exists</code>: nombre de fois où la valeur mise à jour d’une ligne viole une contrainte unique NOT DEFERRABLE.</li><li><code>confl_update_missing</code>: nombre de fois où le tuple à mettre à jour est manquant.</li><li><code>confl_delete_origin_differs</code>: nombre de fois où une suppression a été effectuée sur une ligne déjà modifiée par une autre origine.</li><li><code>confl_delete_missing</code>: nombre de fois où le tuple à supprimer est manquant.</li></ul><h3 id=\"avance\"><a href=\"https://www.data-bene.io/fr/blog/statistiques-cumulatives-dans-postgresql-18/#avance\" class=\"heading-anchor\">Avancé</a></h3><p>Un <a href=\"https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-ADMIN-STATSMOD\" rel=\"noopener\">nouveau jeu de fonctions</a> permet désormais de gérer les statistiques de relations et d’attributs (<code>relpages</code>, <code>avg_width</code>, etc.). Cela offre la possibilité d’exporter, importer et ajuster les stats à volonté, afin de répliquer le comportement du planificateur hors production, de maintenir des stats corrigées, et plus encore.</p><h3 id=\"mon-prefere-pour-les-auteurs-dextensions-la-nouvelle-api-c-de-stats\"><a href=\"https://www.data-bene.io/fr/blog/statistiques-cumulatives-dans-postgresql-18/#mon-prefere-pour-les-auteurs-dextensions-la-nouvelle-api-c-de-stats\" class=\"heading-anchor\">Mon préféré pour les auteurs d’extensions: la nouvelle API C de stats</a></h3><p>L’une des évolutions les plus enthousiasmantes est ce que PostgreSQL 18 <em>ouvre</em> aux auteurs d’extensions.</p><p>Cette petite ligne au bas de la section <a href=\"https://www.postgresql.org/docs/18/release-18.html#RELEASE-18-MODULES\" rel=\"noopener\">E.1.3.9 Modules</a> est celle qui nous intéresse :</p><blockquote><p>Allow extensions to use the server’s cumulative statistics API (Michael Paquier)</p></blockquote><p>Jusqu’ici, la manipulation des statistiques était réservée à l’interne ; désormais, une API officielle et structurée est disponible pour construire (ou envelopper) autour.</p><p>Le <a href=\"https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=7949d9594\" rel=\"noopener\">message de commit</a> est bien rédigé et couvre l’essentiel des nouveautés. Un sous-ensemble des options est <a href=\"https://www.postgresql.org/docs/18/xfunc-c.html#XFUNC-ADDIN-CUSTOM-CUMULATIVE-STATISTICS\" rel=\"noopener\">détaillé dans la documentation</a>. Cependant, il faut encore plonger dans le code source pour en savoir plus ; en particulier, il vaut la peine de regarder l’extension <code>injection points</code> (fournie avec PostgreSQL) qui utilise cette nouvelle API.</p><p>Pour aller plus loin sur la manière dont une extension peut exploiter ces nouvelles capacités, vous pourrez bientôt découvrir <strong>PACS (PostgreSQL Advanced Cumulative Statistics)</strong> sur Codeberg : mon projet qui propose une bibliothèque de wrappers et des utilitaires autour des nouvelles APIs de statistiques de PostgreSQL 18.</p><p>En attendant, la présentation que j’ai donnée à <a href=\"https://archive.fosdem.org/2025/schedule/event/fosdem-2025-4496-stats-roll-baby-stats-roll-/\" rel=\"noopener\">FOSDEM 2025</a> explore ce sujet plus en détail.</p></body></html>\n",
      "date_published": "2025-09-29T00:00:00Z"
    }
    ,{
      "id": "https://www.data-bene.io/fr/blog/base-de-donnees-la-plus-desiree-trois-annees-consecutives/",
      "url": "https://www.data-bene.io/fr/blog/base-de-donnees-la-plus-desiree-trois-annees-consecutives/",
      "title": "Base de données la plus désirée trois années consécutives : L&#39;attrait de PostgreSQL pour les développeurs",
      "content_html": "\n<html><head></head><body><p>PostgreSQL vit plus qu’un simple moment de gloire—elle établit un schéma clair d’excellence soutenue. Pour la troisième année consécutive, cette base de données pilotée par la communauté a revendiqué la première place dans les résultats 2025 de l’enquête annuelle des développeurs de Stack Overflow, et les résultats révèlent à la fois ce que les développeurs valorisent aujourd’hui et où se dirige le paysage des bases de données.</p><p>Les résultats de l’enquête montrent que PostgreSQL est classée au plus haut rang parmi toutes les technologies de bases de données pour les développeurs qui veulent l’utiliser dans la prochaine année (47%) ou l’ont utilisée cette année et veulent continuer à l’utiliser l’année prochaine (66%) pour la troisième année d’affilée.</p><h2 id=\"les-chiffres-racontent-une-histoire-convaincante\"><a href=\"https://www.data-bene.io/fr/blog/base-de-donnees-la-plus-desiree-trois-annees-consecutives/#les-chiffres-racontent-une-histoire-convaincante\" class=\"heading-anchor\">Les chiffres racontent une histoire convaincante</a></h2><p>Les données de l’enquête de plus de 49 000 développeurs à travers 177 pays fournissent une preuve claire de l’attrait soutenu de PostgreSQL. Depuis 2023, PostgreSQL s’est constamment classée comme la technologie de base de données la plus désirée et la plus admirée parmi les développeurs.</p><p>En regardant les mesures spécifiques des visualisations de l’enquête, PostgreSQL mène avec 46,5% des développeurs voulant travailler avec elle dans l’année à venir, tandis qu’un impressionnant 65,5% de ceux qui l’ont utilisée veulent continuer à le faire. Ce ne sont pas seulement des chiffres impressionnants—ils représentent une cohérence qui est rare dans le paysage technologique en rapide évolution.</p><p>Les données de l’enquête révèlent également un schéma intéressant parmi les développeurs utilisant actuellement d’autres technologies de bases de données. Les développeurs travaillant avec MongoDB et Redis montrent un désir particulièrement fort d’ajouter PostgreSQL à leur boîte à outils l’année prochaine, voyant la valeur d’ajouter des compétences en bases de données relationnelles à leur répertoire.</p><h2 id=\"lavantage-communautaire-en-action\"><a href=\"https://www.data-bene.io/fr/blog/base-de-donnees-la-plus-desiree-trois-annees-consecutives/#lavantage-communautaire-en-action\" class=\"heading-anchor\">L’avantage communautaire en action</a></h2><p>Pourquoi PostgreSQL a-t-elle atteint ce niveau de succès soutenu ? La réponse réside dans son modèle de développement piloté par la communauté. En tant que projet open source, PostgreSQL bénéficie d’un développement collaboratif qui est à la fois transparent et réactif aux besoins du monde réel.</p><p>Le projet PostgreSQL représente le meilleur de ce que le développement piloté par la communauté peut accomplir. Avec plus de 400 contributeurs de code à travers plus de 140 entreprises de soutien, le projet se vante de plus de 55 000 commits et plus de 1,6 million de lignes de code soigneusement élaboré. Cette approche diverse et globalement distribuée du développement résulte en des tests plus approfondis, des corrections de bogues plus rapides, et des fonctionnalités plus innovantes que les modèles de développement commercial traditionnels n’atteignent typiquement.</p><p>Les versions majeures sont publiées annuellement avec approximativement 180 fonctionnalités par version, complétées par des versions mineures trimestrielles qui incluent de nombreuses améliorations et corrections. Cette cadence régulière d’innovation constamment contribuée par des individus partout dans le monde assure que PostgreSQL ne fait pas que suivre le rythme des besoins des développeurs—elle les anticipe. Plus que cela, chaque individu a la capacité de contribuer au projet pour s’assurer que partout où le logiciel prend du retard, la fonctionnalité change pour répondre aux demandes modernes.</p><h2 id=\"plus-quune-simple-base-de-donnees-relationnelle\"><a href=\"https://www.data-bene.io/fr/blog/base-de-donnees-la-plus-desiree-trois-annees-consecutives/#plus-quune-simple-base-de-donnees-relationnelle\" class=\"heading-anchor\">Plus qu’une simple base de données relationnelle</a></h2><p>Un facteur clé dans l’attrait large de PostgreSQL est qu’elle n’est pas limitée à être juste un système de base de données relationnelle. PostgreSQL est objet-relationnelle par conception, capable de gérer des types de données diverses incluant JSON/JSONB, XML, Clé-Valeur, géométriques, géospatiales, UUID natif, et données de séries temporelles. Cette polyvalence explique pourquoi les développeurs de milieux NoSQL trouvent PostgreSQL attractive—elle offre la fiabilité relationnelle tout en maintenant la flexibilité à laquelle ils sont habitués.</p><p>Le soutien étendu pour différents types de données, combiné avec les caractéristiques ACID (Atomicité, Cohérence, Isolation, Durabilité), permet une gestion de données optimisée, performante, et fiable indépendamment des exigences spécifiques en place. De plus, l’énorme réseau d’extensions piloté par la communauté de PostgreSQL s’appuie sur son extensibilité native, fournissant des solutions pour la gestion géospatiale, la récupération après sinistre, l’infrastructure de haute disponibilité, la surveillance, l’audit, et bien plus.</p><h2 id=\"le-paysage-plus-large-des-bases-de-donnees\"><a href=\"https://www.data-bene.io/fr/blog/base-de-donnees-la-plus-desiree-trois-annees-consecutives/#le-paysage-plus-large-des-bases-de-donnees\" class=\"heading-anchor\">Le paysage plus large des bases de données</a></h2><p>Tandis que PostgreSQL domine les positions de tête, l’enquête révèle un écosystème de bases de données sain et compétitif. Les classements complets montrent :</p><p><strong>Bases de données les plus désirées :</strong><br>• PostgreSQL : 46,5%<br>• SQLite : 28,3%<br>• Redis : 23,5%<br>• MySQL : 20,5%<br>• MongoDB : 17,6%</p><p><strong>Bases de données les plus admirées :</strong><br>• PostgreSQL : 65,5%<br>• SQLite : 59%<br>• Redis : 54,9%<br>• MongoDB : 45,7%<br>• MySQL : 43,2%</p><p>Ces chiffres reflètent un écosystème diversifié où différentes bases de données servent des objectifs spécifiques. La forte performance de SQLite souligne l’importance continue des solutions légères et intégrées. Redis maintient sa position comme une base de données spécialisée hautement considérée pour la mise en cache et les applications temps réel. Les bases de données traditionnelles comme MySQL et Microsoft SQL Server continuent de détenir des positions significatives, tandis que les nouvelles technologies comme DuckDB montrent des scores d’admiration impressionnants malgré des taux d’utilisation plus faibles.</p><h2 id=\"la-fondation-du-succes-durable-de-postgresql\"><a href=\"https://www.data-bene.io/fr/blog/base-de-donnees-la-plus-desiree-trois-annees-consecutives/#la-fondation-du-succes-durable-de-postgresql\" class=\"heading-anchor\">La fondation du succès durable de PostgreSQL</a></h2><p>Trois années consécutives au sommet des préférences des développeurs n’arrive pas par accident. La domination soutenue de PostgreSQL découle de forces fondamentales qui continuent de bien servir les développeurs alors que les paysages technologiques changent. La résilience intégrée dans PostgreSQL à travers son modèle de développement piloté par la communauté signifie qu’elle s’adapte sans perdre la stabilité. Son extensibilité la distingue de manières pratiques—plutôt que d’attendre les feuilles de route des fournisseurs ou de s’inquiéter des lacunes de fonctionnalités, les développeurs peuvent construire ce dont ils ont besoin ou tirer parti de l’écosystème étendu d’extensions communautaires. La nature open source assure que PostgreSQL reste focalisée sur les besoins des développeurs plutôt que sur les modèles d’affaires, avec des corrections de bogues qui se produisent rapidement et des fonctionnalités qui se développent basées sur des cas d’usage du monde réel.</p><p>Après 35 ans de développement actif et trois années consécutives comme la technologie de base de données la plus désirée, PostgreSQL a prouvé que le développement open source piloté par la communauté peut livrer à la fois une utilité immédiate et une valeur à long terme. Pour les développeurs et organisations regardant leurs choix de bases de données, PostgreSQL offre quelque chose d’increasingly rare : une technologie qui s’améliore avec le temps sans laisser ses utilisateurs derrière.</p></body></html>\n",
      "date_published": "2025-08-09T00:00:00Z"
    }
    ,{
      "id": "https://www.data-bene.io/fr/blog/retour-de-how2025/",
      "url": "https://www.data-bene.io/fr/blog/retour-de-how2025/",
      "title": "Retour de HOW2025",
      "content_html": "\n<html><head></head><body><p>Les 27 et 28 juin se tenaient les conférences Highgo Open World, consacrées à l’écosystème PostgreSQL et au projet IvorySQL. Côté chiffres, le succès est notable : près de 1 000 participants sur place, jusqu’à 8 000 connexions simultanées sur les streams, et environ 25 000 spectateurs au total.</p><p>Le programme comptait 101 conférences techniques animées par 105 intervenants. La majorité des sessions étaient en mandarin, avec un track anglophone proposé en traduction simultanée. Vous pouvez consulter le programme complet sur <a href=\"https://ivorysql.io/schedule/\" rel=\"noopener\">IvorySQL.io</a> et retrouver les replays sur Weibo via <a href=\"https://ivorysql.io/2025/06/27/live-access-june27/\" rel=\"noopener\">ce lien.</a></p><p>Nous étions un petit groupe de la communauté internationale présents, dont <a href=\"https://postgresql.life/post/grant_zhou/\" rel=\"noopener\">Grant Zhou</a> qui assure entre autre la liaison et la collaboration avec l’association PostgreSQL en Chine et dans le reste du monde.</p><p>Sur le plan technique, le contenu était dense et particulièrement intéressant. J’ai retenu notamment :</p><ul class=\"list\"><li><p>La présentation d’Alena Rybakina sur le planificateur de requêtes PostgreSQL et les stratégies pour contourner certaines limites.</p></li><li><p>Un focus clair et concret sur Patroni (Haute-Disponibilité) par Alexander Kukushkin et Polina Bungina.</p></li><li><p>Florentz Tselai a présenté 2 sujets en appliquant ses préceptes: simplicité efficacité, sur l’utilisation de «l’IA» avec PostgreSQL et la gestion des données avec comme support Sun Tzu et les 36 stratagèmes.</p></li><li><p>Également une très bonne introduction à Bazel et son utilisation pour Monogres (à découvrir bientôt) présenté avec énergie par Alvaro Hernandez.</p><p>Monogres est une initiative très intéressante qui doit permettre de renforcer le contrôle de la supply chain logicielle, un thème majeur dans l’IT de nos jours. Et j’y ai aussi vu une très belle occasion d’offrir une vitrine a des variations de PostgreSQL avec des fonctionnalités et des correctifs dont l’inclusion dans PostgreSQL lui-même même ou le backport dans des version majeures précédentes n’est pas toujours possible.</p></li><li><p>Michael Meskes avait l’honneur d’une conférence plénière pour un sujet qui le mérite largement: « From Code to Commerce: Open Source Business Models Today », une keynote sur l’open-source et les logiciels libres, appliqués à l’écosystème PostgreSQL.</p></li><li><p>Mon collègue Andrea a présenté les évolutions et les tendances des entreprises pour transiter vers IvorySQL et PostgreSQL</p></li><li><p>Pour ma part, j’ai présenté linux PSI dans le contexte PostgreSQL.</p></li></ul><p>Comme tout est en streaming, je vous encourage à aller explorer et visionner les sujets qui vous intéressent. Il y a ausi des conférences en anglais pré-enregistrées mais j’avoue avoir profité des créneaux pour échanger avec des participants.</p><p>En apparté des conférences, j’ai eu la chance de rencontrer plusieurs membres de la communauté PostgreSQL chinoise très réputés pour leur implication dans le succès de PostgreSQL localement. J’ai eu aussi l’occasion d’en apprendre d’avantage sur Cloudberry, en remplacement de Greenplum, merci Dianjin Wang!</p><hr><p>Pour Data Bene s’était également un moment prévu pour rencontrer l’équipe en charge d’IvorySQL, basée en grande partie dans le Shandong, la province où se trouve Jinan, ville hôte des conférences. Ivory est un projet auquel nous participons activement et qui permet aux entreprises de s’affranchir d’Oracle «en douceur». C’est un sujet important pour nos clients et qui occupe un place prépondérante dans notre partenariat avec Highgo: ils portent ce projet depuis plusieurs années déjà et nous voulons permettre aux entreprises européenes d’en profiter avec un accompagnement et expertise adaptée.</p><hr><p>Les conférences étaient très bien organisées et l’acceuil formidable, le «Social Event» au «beer garden» local parfaitement adapté à la chaleur de Jinan fin juin!</p><p>Vu le programme des conférences j’ai amèrement regreté de ne rien comprendre (Il y avait 1 track en Anglais et 5 en Mandarin) … mais il se dit déjà que l’an prochain les conférences en Mandarin pourraient peut être être traduites (en anglais), et la date avancée en Mai pour profiter d’un climat plus doux.</p><p>Il y a tellement à y apprendre que j’y retournerai avec grand plaisir.</p></body></html>\n",
      "date_published": "2025-07-14T00:00:00Z"
    }
    ,{
      "id": "https://www.data-bene.io/fr/blog/scale-22x-r%C3%A9unir-la-communaut%C3%A9-open-source-%C3%A0-pasadena/",
      "url": "https://www.data-bene.io/fr/blog/scale-22x-r%C3%A9unir-la-communaut%C3%A9-open-source-%C3%A0-pasadena/",
      "title": "SCaLE 22x : réunir la communauté open source à Pasadena",
      "content_html": "\n<html><head></head><body><p>Le Southern California Linux Expo (SCaLE) 22x, reconnu comme la plus grande conférence d’Amérique du Nord gérée par la communauté et axée sur l’open source et le logiciel libre, s’est tenu au Pasadena Convention Center du 6 au 9 mars 2025. <em>Quand je dis géré par la communauté, je le pense vraiment — pas de patrons corporatifs dictant l’agenda, juste un pur enthousiasme open source qui anime quatre jours de discussions techniques et de collaboration.</em></p><p>La conférence de cette année s’est centrée sur les thèmes de l’IA, du DevOps et des technologies cloud-native, de l’engagement de la communauté open source, de la sécurité et de la conformité, des systèmes et de l’infrastructure, ainsi que du FOSS @ home (explorer le monde des applications auto-hébergées et des services cloud).</p><p>La conférence a attiré des participants venus du monde entier pour tout discuter autour de l’open source, le Linux au cœur bien sûr, tout en poursuivant la discussion sur des sujets tels que les systèmes embarqués et l’IoT. Comme toujours, un mélange unique de discussions technologiques de pointe et de résolution pratique de problèmes dans chaque espace est ce qui rend SCaLE spécial.</p><h2 id=\"conduire-les-elephants-postgresql@scale22x\"><a href=\"https://www.data-bene.io/fr/blog/scale-22x-r%C3%A9unir-la-communaut%C3%A9-open-source-%C3%A0-pasadena/#conduire-les-elephants-postgresql@scale22x\" class=\"heading-anchor\"><strong>Conduire les éléphants : PostgreSQL@SCaLE22x</strong></a></h2><p>PostgreSQL@SCaLE22x s’est déroulé comme un événement dédié de deux jours et deux sessions, les 6 et 7 mars 2025, reconnu dans le cadre des directives des événements communautaires du PostgreSQL Global Development Group. L’équipe de sélection comprenait Gabrielle Roth, Joe Conway et Mark Wong, garantissant la qualité qu’on attend de la communauté PostgreSQL.</p><p>La liste des intervenants était impressionnante : Magnus Hagander, Christophe Pettus, Peter Farkas, Devrim Gündüz, Hamid Akhtar, Henrietta Dombrovskaya, Shaun Thomas, Gülçin Yıldırım Jelínek &amp; Andrew Farries, Nick Meyer et Jimmy Angelakos. Une session particulièrement mémorable s’intitulait “Row-Level Security Sucks. Can We Make It Usable ?” — une prise de position honnête et rafraîchissante sur la fonctionnalité RLS de PostgreSQL qui a probablement résonné auprès de plus d’un administrateur de base de données dans le public.</p><p>Le panel communautaire “Posez-nous vos questions” a été animé par Stacey Haysler et a compté Christophe Pettus, Devrim Gündüz, Jimmy Angelakos, Magnus Hagander et Mark Wong. C’est lors de ces sessions que le véritable transfert de connaissances a lieu — pas de discours marketing, juste des praticiens discutant entre pairs des mécanismes internes de PostgreSQL, des performances, des bonnes pratiques et de l’avenir de la base de données.</p><p>Dans les coulisses, les bénévoles Derya Gumustel, Erika Miller, Hamid Akhtar, Jennifer Scheuerell, Mark Wong et Roberto Mello ont tout fait fonctionner sans accroc, PGUS ayant assuré le stand dans le hall d’exposition.</p><p>Personnellement, j’ai eu le plaisir de collaborer avec Jimmy Angelakos lors de ses <a href=\"https://vyruss.org/blog/scale-22x-live-streams-row-level-security-sucks.html\" rel=\"noopener\">sessions de streaming en direct</a> avec d’autres invités comme Henrietta Dombrovskaya, Mark Wong, Gülçin Yıldırım Jelínek, et même une brève apparition de Devrim Gündüz.</p><p><em>L’un des sujets discutés avec Gülçin Yıldırım Jelínek dans le podcast est de savoir s’il y a un intérêt communautaire pour poursuivre <a href=\"https://www.youtube.com/watch?v=WwaJd2c9whM\" rel=\"noopener\">Postgres Café</a>. Qu’en pensez-vous ? Souhaitez-vous voir plus d’épisodes de cette série de podcast, élargissant les discussions sur les extensions et le développement open source au reste de la communauté et au-delà ? Dites-le nous : <a href=\"mailto:contact@data-bene.io\">contact@data-bene.io</a></em></p><h2 id=\"quelque-chose-pour-tout-le-monde\"><a href=\"https://www.data-bene.io/fr/blog/scale-22x-r%C3%A9unir-la-communaut%C3%A9-open-source-%C3%A0-pasadena/#quelque-chose-pour-tout-le-monde\" class=\"heading-anchor\"><strong>Quelque chose pour tout le monde</strong></a></h2><p>Il y a beaucoup d’événements colocalisés en plus de PostgreSQL @ SCaLE, dont “SCaLE : The Next Generation (TNG)”, un événement technologique axé sur la jeunesse encourageant des activités interactives et des présentations pour les étudiants, ainsi que le concours annuel Cybersecurity Capture the Flag (CTF) présenté par Cal Poly FAST et Pacific Hackers.</p><p>SCaLE reste un excellent endroit pour réseauter en vue d’avancer dans sa carrière dans l’open source. Se mêler aux stands est toujours un excellent moyen de faire des connexions et de trouver des opportunités, bien sûr, mais la journée Open Source Career Day est également revenue afin d’offrir un espace dédié aux professionnels et aux technologistes en herbe pour qu’ils puissent puiser dans des ressources, des outils, des exemples concrets et un contenu engageant issus des présentations et des ateliers.</p><p>L’amusante tradition de tenir une soirée jeux le samedi avec nourriture et boissons s’est également poursuivie cette année, avec un Trivia Night (présenté par Uncoded) et d’autres activités amusantes comme le lancer de hache gonflable, la cible Nerf, les arts et l’artisanat, une salle de jeux de société, une soirée casino et une salle de blocs pour construire des “derby cars” , jouer au pictionary ou construire avec de gros blocs.</p><h2 id=\"gardez-votre-calendrier-libre-pour-scale-23x\"><a href=\"https://www.data-bene.io/fr/blog/scale-22x-r%C3%A9unir-la-communaut%C3%A9-open-source-%C3%A0-pasadena/#gardez-votre-calendrier-libre-pour-scale-23x\" class=\"heading-anchor\"><strong>Gardez votre calendrier libre pour SCaLE 23x</strong></a></h2><p>SCaLE s’est imposé comme une présence constante à Pasadena, et cette stabilité a permis à la conférence de bâtir des relations durables avec la communauté locale et les lieux. Restez à l’affût des annonces de SCaLE 23x — la visite promet d’en valoir la peine.</p><p>Pour ceux qui s’intéressent plus spécifiquement à PostgreSQL@SCaLE, restez attentifs aux listes de diffusion PostgreSQL pour les annonces concernant les opportunités de bénévolat, d’intervention ou d’autres moyens de participer à l’événement de l’année prochaine. Le parcours et le stand PostgreSQL sont une source constante de discussions engageantes parmi ceux de la communauté Postgres et au-delà, reflétant l’adoption croissante de la base de données dans l’industrie.</p><h2 id=\"le-rassemblement-open-source-pour-tous\"><a href=\"https://www.data-bene.io/fr/blog/scale-22x-r%C3%A9unir-la-communaut%C3%A9-open-source-%C3%A0-pasadena/#le-rassemblement-open-source-pour-tous\" class=\"heading-anchor\"><strong>Le rassemblement open source pour tous</strong></a></h2><p>Dans un monde où de nombreuses conférences technologiques ressemblent davantage à des vitrines élaborées pour vendeurs, SCaLE reste ce rassemblement rare où la communauté passe en premier, la collaboration est authentique, et les discussions technologiques sont portées par des praticiens qui résolvent de vrais problèmes. Notez bien SCaLE 23x dans votre calendrier — c’est une conférence qui tient toujours sa promesse de rassembler les enthousiastes de l’open source pour collaborer et apprendre réellement.</p><p>Vous regrettez de ne pas y avoir été ? Vous pouvez toujours consulter <a href=\"https://www.youtube.com/playlist?list=PLh1QjGnfC2eREVHe8shz8Db7jGJvZerCK\" rel=\"noopener\">la playlist YouTube des interventions</a> qui ont été enregistrées lors de la conférence, pour bénéficier au moins du savoir qu’elles contiennent.</p></body></html>\n",
      "date_published": "2025-06-02T00:00:00Z"
    }
    ,{
      "id": "https://www.data-bene.io/fr/blog/sauvegarde-sans-reseau/",
      "url": "https://www.data-bene.io/fr/blog/sauvegarde-sans-reseau/",
      "title": "Il était une fois une base confinée - PostgreSQL, QR Codes et l&#39;art de la sauvegarde sans réseau",
      "content_html": "\n<html><head></head><body><h2 id=\"📦-le-fort-knox-des-bases-de-donnees\"><a href=\"https://www.data-bene.io/fr/blog/sauvegarde-sans-reseau/#%F0%9F%93%A6-le-fort-knox-des-bases-de-donnees\" class=\"heading-anchor\">📦 Le Fort Knox des bases de données</a></h2><p>Il était une fois, dans une salle serveur lointaine, entourée de verre blindé et de béton armé, une base PostgreSQL tellement confinée, tellement isolée, qu’elle ne pouvait que rêver du cloud.</p><p>Pas de réseau.</p><p>Pas d’USB.</p><p>Aucun stockage externe accessible en écriture.</p><p>Juste un clavier, un écran, et le bourdonnement des filtres à air de qualité industrielle.</p><p>Ce n’était pas un simple environnement “air-gapped”. C’était une zone d’exfiltration zéro, avec une sécurité opérationnelle si rigoureuse qu’on aurait cru qu’elle protégeait des secrets d’État — ou pire, un système bancaire des années 80.</p><p>Et pourtant, dans cet oubli numérique, une question demeurait :<br><strong>Comment sauvegarder une base PostgreSQL sans jamais extraire un seul fichier ?</strong></p><hr><h2 id=\"🎥-quand-lecran-devient-ton-reseau\"><a href=\"https://www.data-bene.io/fr/blog/sauvegarde-sans-reseau/#%F0%9F%8E%A5-quand-lecran-devient-ton-reseau\" class=\"heading-anchor\">🎥 Quand l’écran devient ton réseau</a></h2><p>Notre client ne voulait pas juste une sauvegarde. Il <em>en avait besoin</em>. La crainte n’était pas le vol, mais <strong>la perte totale</strong> : une carte mère qui meurt en silence, enfermant les données à jamais dans sa cage de verre. Et dans ce cas, casser le mur à la masse n’est pas un plan de reprise d’activité très élégant.</p><p>Nous avons envisagé toutes les options :</p><ul class=\"list\"><li>OCR d’un défilement de dump SQL ? Trop imprécis.</li><li>Filmer la sortie <code>psql</code> ? Beaucoup trop verbeux.</li><li>Imprimer l’hexadécimal ? On a quand même une conscience.</li></ul><p>Et puis, l’illumination : <strong>les QR codes</strong>.</p><p>Et si on faisait un <code>pg_dump</code> de la base…</p><p>…en QR codes…</p><p>…affichés à l’écran…</p><p>…filmés par une caméra haute fréquence…</p><p>…puis reconstitués image par image à l’extérieur ?</p><p>C’était absurde. Donc forcément prometteur.</p><hr><h2 id=\"🧠-hacking-pg_dump-la-version-pixelisee\"><a href=\"https://www.data-bene.io/fr/blog/sauvegarde-sans-reseau/#%F0%9F%A7%A0-hacking-pg_dump-la-version-pixelisee\" class=\"heading-anchor\">🧠 Hacking <code>pg_dump</code> : la version pixelisée</a></h2><p>L’outil adoré <code>pg_dump</code> de PostgreSQL est modulaire. On l’a donc enrichi d’un nouvel “archiver” : <code>--format=qrcode</code>.</p><p>Voici le fonctionnement :</p><ol class=\"list\"><li><strong>Encodage QR</strong> : chaque portion de sortie SQL est convertie en QR code (format PNG).</li><li><strong>Streaming</strong> : au lieu de sauvegarder les images, on les envoie directement sur <code>stdout</code>.</li><li><strong>Mise en page</strong> : notre interface affiche plusieurs QR codes à l’écran en haute résolution (on parle de 2000+ pixels — de quoi afficher une grille bien dense).</li><li><strong>Capture vidéo</strong> : une machine dédiée avec une caméra 1280Hz filme l’écran et enregistre la séquence complète.</li></ol><p>Pas de macros. Pas de tricherie. Juste des photons et des images.</p><hr><h2 id=\"🔍-reconstruction-a-la-sortie-de-la-cage\"><a href=\"https://www.data-bene.io/fr/blog/sauvegarde-sans-reseau/#%F0%9F%94%8D-reconstruction-a-la-sortie-de-la-cage\" class=\"heading-anchor\">🔍 Reconstruction à la sortie de la cage</a></h2><p>Une fois la vidéo extraite du cube de verre :</p><ul class=\"list\"><li>Notre parseur lit la vidéo image par image.</li><li>Les QR codes sont détectés et décodés en parallèle.</li><li>Chaque bloc est identifié par son numéro de séquence.</li><li>Le tout est réassemblé en un fichier <code>pg_dump.sql</code> complet.</li></ul><p>Et voilà : la base renaît — <strong>entièrement exportée sans transfert numérique</strong>.<br>Rien que de la lumière et des lentilles.</p><hr><h2 id=\"🧩-performances-et-fidelite\"><a href=\"https://www.data-bene.io/fr/blog/sauvegarde-sans-reseau/#%F0%9F%A7%A9-performances-et-fidelite\" class=\"heading-anchor\">🧩 Performances et fidélité</a></h2><ul class=\"list\"><li><strong>QR Version</strong> : Version 40, mode binaire optimisé pour la densité maximale.</li><li><strong>Correction d’erreur</strong> : Niveau Q pour une robustesse accrue.</li><li><strong>Affichage</strong> : Grille 25×16 QR codes sur un écran 1920×1080 — soit 350 blocs par image (environ 1 Mo par frame).</li><li><strong>Vitesse de lecture</strong> : ~60 images/seconde → 21 000 blocs/seconde ≈ 60 Mo/s !</li><li><strong>Durée totale</strong> : Une sauvegarde logique complète de moins de 6 Go exportée en moins de 100 minutes !</li></ul><hr><h2 id=\"🛡️-pourquoi-cest-important\"><a href=\"https://www.data-bene.io/fr/blog/sauvegarde-sans-reseau/#%F0%9F%9B%A1%EF%B8%8F-pourquoi-cest-important\" class=\"heading-anchor\">🛡️ Pourquoi c’est important</a></h2><p>Ce n’est pas juste une anecdote technique — c’est une preuve que <strong>la souplesse de PostgreSQL s’étend jusqu’à l’absurde</strong>. Les environnements ultra-sécurisés ne sont pas rares : défense, finance, infrastructures critiques… Et quand les outils classiques ne suffisent plus, l’architecture extensible de PostgreSQL permet d’innover, même en milieu extrême.</p><p>Chez <strong>Data Bene</strong>, on vit pour ce genre de défi. Optimiser les plans d’exécution ou imaginer des méthodes d’exfiltration qui ressemblent à de l’espionnage, c’est notre terrain de jeu.</p><hr><p><em>Envie d’essayer ? Écrivez-nous — on adore les sauvegardes bizarres.</em></p><p><em>Et si jamais vous pensez à utiliser <code>pg_restore</code> en spectacle laser, appelez-nous. On est curieux.</em></p></body></html>\n",
      "date_published": "2025-04-01T00:00:00Z"
    }
    ,{
      "id": "https://www.data-bene.io/fr/blog/postgres-cafe-contribuer-a-l-open-source/",
      "url": "https://www.data-bene.io/fr/blog/postgres-cafe-contribuer-a-l-open-source/",
      "title": "Postgres Café : Contribuer à l&#39;Open Source",
      "content_html": "\n<html><head></head><body><p>C’est notre sixième épisode de <a href=\"https://www.youtube.com/watch?v=WwaJd2c9whM\" rel=\"noopener\">Café Postgres</a>, un podcast collaboratif de <a href=\"https://www.data-bene.io/en/\" rel=\"noopener\">Data Bene</a> &amp; <a href=\"https://xata.io/\" rel=\"noopener\">Xata</a> où nous discutons de tout, des extensions PostgreSQL aux contributions de la communauté. Dans l’épisode d’aujourd’hui, Sarah Conway et Gülçin Yıldırım Jelinek recontrent Andrea Cucciniello pour discuter de la manière dont les entreprises et les particuliers peuvent contribuer aux projets open source, et des raisons pour lesquelles ils pourraient envisager de le faire.</p><h2 id=\"episode-6-developpement-dextensions-postgresql-la-communaute-et-au-dela\"><a href=\"https://www.data-bene.io/fr/blog/postgres-cafe-contribuer-a-l-open-source/#episode-6-developpement-dextensions-postgresql-la-communaute-et-au-dela\" class=\"heading-anchor\">Épisode 6 : Développement d’extensions PostgreSQL, la communauté et au-delà</a></h2><p>À quelle fréquence les entreprises expriment-elles leur intérêt pour une contribution open source ? Il est évident que toute aide apportée profite directement aux projets open source. Mais y a-t-il des avantages pour l’entreprise qui contribue ? Quels sont les modes de contribution qu’une entreprise peut envisager ? Ce sont des questions que nous entendons souvent. Explorons donc certaines des réponses évoquées dans cet épisode à travers un bref récapitulatif.</p><h3 id=\"contribuer-aux-projets-et-aux-communautes-open-source\"><a href=\"https://www.data-bene.io/fr/blog/postgres-cafe-contribuer-a-l-open-source/#contribuer-aux-projets-et-aux-communautes-open-source\" class=\"heading-anchor\">Contribuer aux projets et aux communautés open source</a></h3><p>Chez Data Bene, nous avons déjà quelques clients intéressés par le développement de fonctionnalités ou d’améliorations pour l’écosystème PostgreSQL.</p><p>Ces entreprises souhaitent corriger des bugs et ajouter de nouvelles fonctionnalités qui complètent leurs cas d’utilisation et leurs piles technologiques dans PostgreSQL, Citus Data et les technologies associées pour accomplir deux choses :</p><ol class=\"list\"><li>Pour créer les fonctionnalités dont ils ont besoin, qui sont nativement intégrées au logiciel en amont et maintenues de manière transparente par la grande communauté open source, et</li><li>Pour garantir que d’autres personnes ayant un cas d’utilisation similaire puissent également tirer parti de ces avantages.</li></ol><p>Les temps changent ; la seule façon pour le logiciel source de rester pertinent, utile et bénéfique pour le public mondial qui l’utilise est de bénéficier de contributions mondiales, garantissant qu’il répond toujours aux besoins réels des utilisateurs d’année en année.</p><h3 id=\"pourquoi-soutenir-des-projets-open-source\"><a href=\"https://www.data-bene.io/fr/blog/postgres-cafe-contribuer-a-l-open-source/#pourquoi-soutenir-des-projets-open-source\" class=\"heading-anchor\">Pourquoi soutenir des projets open source ?</a></h3><p>La dépendance vis-à-vis des fournisseurs est un problème majeur dans le secteur des logiciels et des services ; contribuer aux projets open source garantit que la technologie ouvertement développée peut continuer à l’être. L’utilisation de la technologie FOSS signifie que vous évitez d’investir dans une entreprise qui pourrait fermer le code ou en restreindre l’accès, donnant ainsi à l’utilisateur final la liberté de continuer à utiliser et à développer des outils essentiels qui font partie de sa pile technologique.</p><p>Ce type de logiciel est également soumis à un processus de développement très visible, ce qui signifie qu’il est beaucoup plus difficile d’intégrer dans le code sous-jacent des atteintes à la vie privée, des vulnérabilités de cybersécurité, etc.</p><p>De plus, les logiciels open source sont créés par des individus du monde entier ayant des perspectives et des parcours variés ; cela garantit qu’ils sont minutieusement testés, et intègrent un large éventail de fonctionnalités intégrées qui sont <em>réellement utiles</em> à de nombreux utilisateurs finaux. Cela permet à ce type de projets d’être couronnés de succès pendant de nombreuses années, aussi longtemps qu’il existe une communauté prête à les soutenir.</p><p><em>Exemple concret : PostgreSQL existe depuis plus de 35 ans de développement actif et figure toujours aujourd’hui en tête des enquêtes et des classements des développeurs comme étant la solution de base de données la plus appréciée, la plus utilisée et la plus populaire au monde !</em></p><h3 id=\"comment-les-entreprises-peuvent-elles-soutenir-au-mieux-les-projets-open-source\"><a href=\"https://www.data-bene.io/fr/blog/postgres-cafe-contribuer-a-l-open-source/#comment-les-entreprises-peuvent-elles-soutenir-au-mieux-les-projets-open-source\" class=\"heading-anchor\">Comment les entreprises peuvent-elles soutenir au mieux les projets open source ?</a></h3><p>Il existe quelques moyens clés pour atteindre cet objectif final :</p><ol class=\"list\"><li><strong>Incluez les contributions de code au temps de travail de vos ingénieurs.</strong> Lorsque vous allouez du temps aux développeurs pour travailler sur le code en amont, vous vous assurez que la technologie que vous exploitez (pour fournir un support et/ou des services, pour alimenter votre produit ou sur laquelle repose votre infrastructure) bénéficie de performances améliorées, de fonctionnalités étendues, de problèmes résolus ou de corrections de bugs.</li><li><strong>Envisagez de développer des extensions.</strong> La création et la maintenance d’extensions permettent aux entreprises d’ajouter des fonctionnalités spécialisées ou de répondre à certains cas d’utilisation sans altérer la base de code principale. Dans le cas de PostgreSQL en particulier, cette extensibilité permet à Postgres de répondre aux besoins de différents secteurs, utilisateurs et entreprises, avec un écosystème polyvalent et solide. Ce type de système modulaire permet à PostgreSQL d’évoluer sans complexifier trop son noyau, ce qui rend le projet dans son ensemble plus facile à gérer et à mettre à jour.</li><li><strong>Sponsorisez, organisez et participez à des événements.</strong> En tant qu’entreprise, vous pouvez choisir de promouvoir ou d’initier des conférences technologiques, des groupes d’utilisateurs, des ateliers et bien plus encore pour sensibiliser et éduquer le grand public sur la technologie que vous souhaitez voir prospérer. Les événements sont un excellent moyen pour les utilisateurs et les développeurs de collaborer, de discuter des avancées et de partager les meilleures pratiques, ce qui renforce la communauté et améliore le produit en conséquence.</li></ol><h3 id=\"comment-data-bene-contribue\"><a href=\"https://www.data-bene.io/fr/blog/postgres-cafe-contribuer-a-l-open-source/#comment-data-bene-contribue\" class=\"heading-anchor\">Comment Data Bene contribue</a></h3><p>Cédric Villemain, président de Data Bene, a développé <a href=\"https://codeberg.org/c2main/pgfincore\" rel=\"noopener\">pg_fincore</a> et travaille actuellement sur <a href=\"https://codeberg.org/data-bene/statsmgr\" rel=\"noopener\">StatsMgr</a>, pg_psi et d’autres composants conçus pour améliorer les capacités statistiques de Postgres.</p><p>Notre équipe est également responsable d’un certain nombre de contributions dans le cadre de projets tels que <a href=\"https://www.citusdata.com/blog/2025/02/06/distribute-postgresql-17-with-citus-13/\" rel=\"noopener\">Citus Data</a> et <a href=\"https://github.com/zammad/zammad/\" rel=\"noopener\">Zammad</a>.</p><p>Nous nous efforçons de sponsoriser, de présenter et de promouvoir des conférences et des groupes d’utilisateurs de la communauté PostgreSQL ou open source, tels que PostgreSQL Europe, pgDay Paris, AlpOSS, Capitole du Libre, et bien d’autres. Certains membres de notre équipe ont également initié ou font partie des comités d’organisation de divers événements tels que les groupes d’utilisateurs PostgreSQL de Barcelone et de Madrid et pgDay Lowlands. L’impact des événements sur le projet et la communauté dans son ensemble ne peut être sous-estimé, et il est important pour nous d’y contribuer de cette manière.</p><p>Enfin, nous aidons les clients à comprendre comment contribuer à PostgreSQL et à des projets open source similaires. Par le biais de formations, d’ateliers et de collaborations, nous les encourageons à apporter des contributions significatives qui correspondent à leurs objectifs et soutiennent la communauté dans son ensemble.</p><p><em>Si vous êtes un développeur souhaitant contribuer à l’écosystème open source et/ou PostgreSQL, ou aider les clients avec leurs besoins en R&amp;D, notre équipe s’agrandit : rendez-nous visite sur notre <a href=\"https://data-bene.io/en/jobs\" rel=\"noopener\">site web</a> pour voir les postes disponibles!</em></p><h3 id=\"regardez-lepisode-complet\"><a href=\"https://www.data-bene.io/fr/blog/postgres-cafe-contribuer-a-l-open-source/#regardez-lepisode-complet\" class=\"heading-anchor\">Regardez l’épisode complet</a></h3><p>Vous souhaitez regarder la discussion dans son intégralité ? Elle est disponible sur YouTube (en anglais uniquement) :</p><iframe width=\"560\" height=\"315\" src=\"https://www.youtube-nocookie.com/embed/BYvXQB9O71U?si=-irKIHXxwiPhBFQP\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen=\"\"></iframe><h3 id=\"restez-a-lecoute-pour-plus-doutils-postgres\"><a href=\"https://www.data-bene.io/fr/blog/postgres-cafe-contribuer-a-l-open-source/#restez-a-lecoute-pour-plus-doutils-postgres\" class=\"heading-anchor\">Restez à l’écoute pour plus d’outils Postgres</a></h3><p>A ce jour, nous avons terminé notre première série d’épisodes pour Postgres Café ! D’autres épisodes pourraient suivre, ou pas. Suivez-nous sur les réseaux sociaux (comme <a href=\"https://www.linkedin.com/company/91744288\" rel=\"noopener\">LinkedIn</a> ou <a href=\"https://fosstodon.org/@data_bene\" rel=\"noopener\">Mastodon</a>) pour être informé des prochaines sorties. (Voulez-vous en savoir plus sur cette série de podcasts ? Faites-le nous savoir !)</p><p><a href=\"https://www.youtube.com/playlist?list=PLf7KS0svgDP_zJmby3RMzzOVO45qLbruA\" rel=\"noopener\">Abonnez-vous à la playlist</a> ou consultez-le pour des interviews sur les extensions open source comme <a href=\"https://codeberg.org/Data-Bene/StatsMgr\" rel=\"noopener\">StatsMgr</a> pour une gestion efficace des statistiques de PostgreSQL, ou <a href=\"https://youtu.be/j1R3a0-jg6c\" rel=\"noopener\">pgstream</a>, un outil open source de capture de données modifiées (CDC) conçu spécifiquement pour PostgreSQL ou bien d’autres. PostgreSQL est l’une des bases de données les plus extensibles du marché avec un vaste écosystème d’extensions ; apprenez directement des experts en découvrant certaines des options disponibles.</p></body></html>\n",
      "date_published": "2025-03-04T00:00:00Z"
    }
    ,{
      "id": "https://www.data-bene.io/fr/blog/postgres-cafe-deployer-postgresql-distribue-a-grande-echelle-avec-citus-data/",
      "url": "https://www.data-bene.io/fr/blog/postgres-cafe-deployer-postgresql-distribue-a-grande-echelle-avec-citus-data/",
      "title": "Postgres Café : Déployer PostgreSQL distribué à grande échelle avec Citus Data",
      "content_html": "\n<html><head></head><body><p>C’est l’heure du quatrième épisode de <a href=\"https://www.youtube.com/watch?v=WwaJd2c9whM\" rel=\"noopener\">Café Postgres</a>, un podcast de nos équipes de <a href=\"https://www.data-bene.io/en/\" rel=\"noopener\">Data Bene</a> et <a href=\"https://xata.io/\" rel=\"noopener\">Xata</a> où nous discutons de la contribution à PostgreSQL et du développement d’extensions. Dans ce dernier épisode, Sarah Conway et Gülçin Yıldırım Jelinek rencontrent Stéphane Carton pour parler de <a href=\"https://github.com/citusdata/citus\" rel=\"noopener\">Citus Data</a>, une extension entièrement open source de Microsoft qui permet de déployer PostgreSQL distribué à grande échelle.</p><h2 id=\"episode-4-citus-data\"><a href=\"https://www.data-bene.io/fr/blog/postgres-cafe-deployer-postgresql-distribue-a-grande-echelle-avec-citus-data/#episode-4-citus-data\" class=\"heading-anchor\">Épisode 4 : Citus Data</a></h2><p>La base de données Citus a connu 127 versions depuis le 24 mars 2016, date à laquelle elle est passée pour la première fois gratuite et open source pour son utilisation et ses contributions. Il s’agit d’un outil puissant qui fonctionne nativement avec PostgreSQL et s’intègre de manière transparente à tous les outils et extensions Postgres. Voici un résumé des points abordés dans cet épisode de podcast !</p><h3 id=\"repondre-aux-problematiques-devolutivite-de-performance-et-de-gestion-des-grands-jeux-de-donnees\"><a href=\"https://www.data-bene.io/fr/blog/postgres-cafe-deployer-postgresql-distribue-a-grande-echelle-avec-citus-data/#repondre-aux-problematiques-devolutivite-de-performance-et-de-gestion-des-grands-jeux-de-donnees\" class=\"heading-anchor\">Répondre aux problématiques d’évolutivité, de performance et de gestion des grands jeux de données</a></h3><p>Pourquoi Citus Data existe-t-il et quels problèmes résout-il ? Examinons cela par catégorie.</p><h4 id=\"developpement\"><a href=\"https://www.data-bene.io/fr/blog/postgres-cafe-deployer-postgresql-distribue-a-grande-echelle-avec-citus-data/#developpement\" class=\"heading-anchor\">Développement</a></h4><p>Citus est conçu pour résoudre le problème de la modélisation des données distribuées en fournissant des méthodes de cartographie de la charge de travail dans les modèles de données distribuées, telles que des tables de partitionnement basées sur des clés primaires (particulièrement utiles pour les microservices et les charges de travail à haut débit).</p><h4 id=\"evolutivite\"><a href=\"https://www.data-bene.io/fr/blog/postgres-cafe-deployer-postgresql-distribue-a-grande-echelle-avec-citus-data/#evolutivite\" class=\"heading-anchor\">Évolutivité</a></h4><p>En distribuant les données sur plusieurs nœuds, vous pouvez activer la mise à l’échelle horizontale des bases de données PostgreSQL.</p><p>Cela permet aux développeurs de combiner les capacités des processeurs, de mémoire, de stockage et des E/S de plusieurs machines pour gérer de grands ensembles de données et des charges de travail à trafic élevé. Il est possible d’ajouter facilement davantage de nœuds au cluster et de rééquilibrer les partitions au fur et à mesure que votre volume de données augmente.</p><h4 id=\"performance\"><a href=\"https://www.data-bene.io/fr/blog/postgres-cafe-deployer-postgresql-distribue-a-grande-echelle-avec-citus-data/#performance\" class=\"heading-anchor\">Performance</a></h4><p>Le moteur de requêtes distribué de Citus est utilisé pour maximiser l’efficacité, en parallélisant les requêtes et en regroupant l’exécution de plusieurs nœuds de travail.</p><p>Même lorsque des milliers, voire des millions d’instructions sont exécutées par seconde, l’ingestion de données est toujours optimisée via la récupération des bonnes partitions, la connexion aux nœuds appropriés et la parallélisation de certaines opérations. Tout cela garantit un débit élevé et une latence faible lors du traitement des données en temps réel.</p><h4 id=\"haute-disponibilite-et-redondance\"><a href=\"https://www.data-bene.io/fr/blog/postgres-cafe-deployer-postgresql-distribue-a-grande-echelle-avec-citus-data/#haute-disponibilite-et-redondance\" class=\"heading-anchor\">Haute disponibilité et redondance</a></h4><p>Grâce au modèle de données distribué, vous pouvez créer des copies redondantes des tables et des partitions sur plusieurs nœuds. Cela permet de garantir que la base de données reste résiliente et disponible même en cas de panne de nœuds, et maintenir ainsi une haute disponibilité.</p><h3 id=\"contribution-a-citus\"><a href=\"https://www.data-bene.io/fr/blog/postgres-cafe-deployer-postgresql-distribue-a-grande-echelle-avec-citus-data/#contribution-a-citus\" class=\"heading-anchor\">Contribution à Citus</a></h3><p>Chez Data Bene, notre objectif est de soutenir la dynamique du code source grâce au développement continu et aux contributions au code. Cédric Villemain, entre autres membres de notre équipe, évalue constamment de nouveaux ajouts de fonctionnalités ou autres améliorations qui peuvent faire une différence pour les utilisateurs.</p><p>Que vous fassiez partie d’une équipe DevOps qui cherche à créer une architecture distribuée pour vos instances PostgreSQL, ou que vous soyez un utilisateur final tel qu’un analyste commercial qui recherche des performances efficaces lors du traitement de grandes quantités de données, Citus Data peut être le meilleur choix.</p><p>Si vous avez des demandes ou des intérêts particuliers en matière de fonctionnalités, notre équipe de Data Bene vous aidera à contribuer directement à Citus Data ou pourra le faire en votre nom pour garantir la longévité du projet Citus et sa pertinence pour vos projets. Apprenez-en davantage sur la contribution à Citus Data en vous référant au dépôt officiel <a href=\"https://github.com/citusdata/citus/blob/main/CONTRIBUTING.md\" rel=\"noopener\">CONTRIBUTING.md</a>.</p><h3 id=\"regardez-lepisode-complet\"><a href=\"https://www.data-bene.io/fr/blog/postgres-cafe-deployer-postgresql-distribue-a-grande-echelle-avec-citus-data/#regardez-lepisode-complet\" class=\"heading-anchor\">Regardez l’épisode complet</a></h3><p>Vous envisagez de regarder la discussion complète ? Découvrez-le sur YouTube :</p><iframe width=\"560\" height=\"315\" src=\"https://www.youtube-nocookie.com/embed/WueRn76nJ9Q?si=ulvzvfcr4Ux17tt0\" title=\"Lecteur vidéo YouTube\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen=\"\"></iframe><h3 id=\"decouvrez-dautres-outils-postgres\"><a href=\"https://www.data-bene.io/fr/blog/postgres-cafe-deployer-postgresql-distribue-a-grande-echelle-avec-citus-data/#decouvrez-dautres-outils-postgres\" class=\"heading-anchor\">Découvrez d’autres outils Postgres</a></h3><p>D’autres épisodes sont en cours de publication au Postgres Café ! <a href=\"https://www.youtube.com/playlist?list=PLf7KS0svgDP_zJmby3RMzzOVO45qLbruA\" rel=\"noopener\">Abonnez-vous à la playlist</a> pour plus d’interviews sur des outils open source comme <a href=\"https://codeberg.org/Data-Bene/StatsMgr\" rel=\"noopener\">StatsMgr</a> pour une gestion efficace des statistiques PostgreSQL, <a href=\"https://github.com/xataio/pgzx\" rel=\"noopener\">pgzx</a> pour la création d’extensions PostgreSQL à l’aide de Zig, etc. Laissez les experts vous présenter de nouvelles extensions à essayer pour optimiser vos déploiements Postgres.</p></body></html>\n",
      "date_published": "2025-01-29T00:00:00Z"
    }
    ,{
      "id": "https://www.data-bene.io/fr/blog/postgres-cafe-developpez-vos-capacities-de-surveillance-avec-statsmgr/",
      "url": "https://www.data-bene.io/fr/blog/postgres-cafe-developpez-vos-capacities-de-surveillance-avec-statsmgr/",
      "title": "Postgres Café : Développez vos capacités de surveillance avec StatsMgr",
      "content_html": "\n<html><head></head><body><p>L’année 2025 a commencé et nous sommes ravis de publier le deuxième épisode de <a href=\"https://www.youtube.com/watch?v=WwaJd2c9whM\" rel=\"noopener\">Postgres Café</a>, une série de blogs et de vidéos de nos équipes chez <a href=\"https://www.data-bene.io/fr/\" rel=\"noopener\">Data Bene</a> et <a href=\"https://xata.io/\" rel=\"noopener\">Xata</a>, réalisée dans le but d’explorer le monde de l’open source et de découvrir ses liens avec l’extensibilité de PostgreSQL. Tout au long de cette série, nous discutons de différentes extensions et des outils qui facilitent la vie des développeurs lorsqu’ils travaillent avec PostgreSQL. Dans notre deuxième épisode, nous explorons une toute nouvelle extension PostgreSQL appelée <a href=\"https://codeberg.org/data-bene/statsmgr\" rel=\"noopener\">StatsMgr</a> qui exploite les processus en tâche de fond (background workers) et la mémoire partagée pour capturer, gérer et interroger diverses statistiques pour WAL, SLRU, IO, checkpointing, etc.</p><h2 id=\"episode-2-statsmgr\"><a href=\"https://www.data-bene.io/fr/blog/postgres-cafe-developpez-vos-capacities-de-surveillance-avec-statsmgr/#episode-2-statsmgr\" class=\"heading-anchor\"><strong>Épisode 2: StatsMgr</strong></a></h2><p>Dans cet épisode nous présentons l’extension open source StatsMgr, récemment publiée, créée pour surveiller et suivre en continu les événements sur PostgreSQL et le système sous-jacent. Voici un aperçu de ce que cet épisode a couvert :</p><h3 id=\"traitement-personnalise-des-metriques\"><a href=\"https://www.data-bene.io/fr/blog/postgres-cafe-developpez-vos-capacities-de-surveillance-avec-statsmgr/#traitement-personnalise-des-metriques\" class=\"heading-anchor\"><strong>Traitement personnalisé des métriques</strong></a></h3><p>À l’origine, l’idée était de fournir une interface simplifiée pour les métriques, tout en les enrichissant avec une grande variété de types disponibles. Cette fonctionnalité a ensuite été étendue pour résoudre des problèmes tels que :</p><ul class=\"list\"><li><strong>Rendre les statistiques disponibles</strong> pour la collecte à partir de systèmes externes, sans interruption même lorsque ces systèmes externes sont en panne.</li><li><strong>Fournir une vue immédiate des statistiques PostgreSQL</strong> avec suivi historique, y compris les vues et fonctions pg_stat.</li><li><strong>Augmenter et réduire la quantité d’enregistrements historiques</strong> en cas de besoin grâce à l’allocation de mémoire tampon dynamique.</li><li><strong>Déboguer des instances PostgreSQL</strong> avec analyse historique et sans redémarrages requis.</li></ul><p>Cette extension est aussi très bien pour gérer des situations telles que lorsque…</p><ul class=\"list\"><li><strong>…votre agent de surveillance est en panne</strong> ; l’utilisation de StatsMgr comme sauvegarde vous permet de vous assurer que vous ne perdrez pas de statistiques dans cet événement, car les événements sont capturés indépendamment et stockés pour être collectés ultérieurement par votre agent de surveillance.</li><li><strong>…vous avez des pics ou un comportement inhabituel sur votre système de production.</strong> Cette extension vous permet d’obtenir un aperçu de l’activité pour des informations de débogage utiles.</li></ul><h3 id=\"collection-etendue-et-historique-de-mesures\"><a href=\"https://www.data-bene.io/fr/blog/postgres-cafe-developpez-vos-capacities-de-surveillance-avec-statsmgr/#collection-etendue-et-historique-de-mesures\" class=\"heading-anchor\"><strong>Collection étendue et historique de mesures</strong></a></h3><p>Actuellement, les types de statistiques pris en charge incluent :</p><ul class=\"list\"><li>WAL</li><li>SLRU</li><li>BGWriter</li><li>Checkpointer</li><li>Archiver</li><li>IO</li></ul><p>Chacun est enregistré auprès d’un gestionnaire qui vous permet de récupérer et de gérer ces statistiques, et est également accompagné de structures de mémoire partagée pour stocker des instantanés historiques.</p><p>Certaines des prochaines étapes du projet comprendront l’ajout de statistiques dynamiques telles que pg_stat_user_tables, entre autres.</p><p>Il reste encore beaucoup de choses à faire, des améliorations subtiles aux nouvelles fonctionnalités majeures. Il existe donc bien sûr de nombreuses opportunités de contribuer au projet, que vous soyez un nouveau venu ou un développeur PostgreSQL confirmé. Vous souhaitez participer à l’effort ? Consultez <a href=\"https://codeberg.org/Data-Bene/StatsMgr/src/branch/main/CONTRIBUTING.md\" rel=\"noopener\">CONTRIBUTING.md</a> dans le projet.</p><h3 id=\"regardez-lepisode-complet\"><a href=\"https://www.data-bene.io/fr/blog/postgres-cafe-developpez-vos-capacities-de-surveillance-avec-statsmgr/#regardez-lepisode-complet\" class=\"heading-anchor\"><strong>Regardez l’épisode complet</strong></a></h3><p>Pour une exploration approfondie de StatsMgr et de ses capacités, regardez l’épisode complet ici :</p><iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/UMzCLFwCPI8?si=_ZCEoWYtFW_UCKXm\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen=\"\"></iframe><h3 id=\"restez-a-lecoute-pour-plus-doutils-postgres\"><a href=\"https://www.data-bene.io/fr/blog/postgres-cafe-developpez-vos-capacities-de-surveillance-avec-statsmgr/#restez-a-lecoute-pour-plus-doutils-postgres\" class=\"heading-anchor\"><strong>Restez à l’écoute pour plus d’outils Postgres</strong></a></h3><p>Il y a encore beaucoup à venir sur Postgres Café. <a href=\"https://www.youtube.com/playlist?list=PLf7KS0svgDP_zJmby3RMzzOVO45qLbruA\" rel=\"noopener\">Abonnez-vous à la playlist</a> pour découvrir des épisodes qui présentent d’autres outils open source comme <a href=\"https://pgroll.com/\" rel=\"noopener\">pgroll</a> pour les migrations de schémas sans interruption de service, ou <a href=\"https://www.citusdata.com/\" rel=\"noopener\">Citus Data</a> une extension pour des bases PostgreSQL distribuées et évolutives, et bien plus encore. Restez en contact pour découvrir comment chaque outil peut rendre le travail avec Postgres plus fluide et plus efficace.</p></body></html>\n",
      "date_published": "2025-01-07T00:00:00Z"
    }
    ,{
      "id": "https://www.data-bene.io/fr/blog/transformations-inattendues-de-types-de-donn%C3%A9es/",
      "url": "https://www.data-bene.io/fr/blog/transformations-inattendues-de-types-de-donn%C3%A9es/",
      "title": "Transformations inattendues des types de données",
      "content_html": "\n<html><head></head><body><h2 id=\"les-types-de-donnees-de-votre-fonction-ont-change-et-vous-navez-pas-ete-informes\"><a href=\"https://www.data-bene.io/fr/blog/transformations-inattendues-de-types-de-donn%C3%A9es/#les-types-de-donnees-de-votre-fonction-ont-change-et-vous-navez-pas-ete-informes\" class=\"heading-anchor\">Les types de données de votre fonction ont changé et vous n’avez pas été informés</a></h2><p>Cet article est le résultat d’une revue de code demandée par l’un de nos clients.</p><p>Notre client a exécuté la commande <code>pg_dump --schema-only</code> pour nous fournir<br>les définitions des objets de niveau <code>database</code> ainsi que le code PLpgsql à auditer.<br>Jusque là, tout allait bien.</p><p>J’ai commencé à lire le code et tout d’un coup je fus pris d’un doute, vous savez<br>le méchant doute qui vous donne l’impression que votre château de cartes va s’écrouler.<br>Voici la fonction que j’avais sous les yeux:</p><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token keyword\">CREATE</span> <span class=\"token keyword\">FUNCTION</span> xxx<span class=\"token punctuation\">(</span> p_id <span class=\"token keyword\">character</span><span class=\"token punctuation\">,</span> p_info <span class=\"token keyword\">character</span> <span class=\"token keyword\">varying</span> <span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">RETURNS</span> <span class=\"token keyword\">integer</span>\n<span class=\"token keyword\">LANGUAGE</span> plpgsql\n<span class=\"token keyword\">AS</span> $$\n<span class=\"token keyword\">DECLARE</span>\n<span class=\"token keyword\">BEGIN</span>\n   <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span>\n   <span class=\"token keyword\">INSERT</span> <span class=\"token keyword\">INTO</span> t1\n   <span class=\"token keyword\">SELECT</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">FROM</span> t2 <span class=\"token keyword\">WHERE</span> t2<span class=\"token punctuation\">.</span>id <span class=\"token operator\">=</span> p_id<span class=\"token punctuation\">;</span>\n   <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span>\n<span class=\"token keyword\">END</span><span class=\"token punctuation\">;</span>\n$$\n<span class=\"token punctuation\">;</span></code></pre><p>Peut-être que la première lecture de la fonction ne vous a pas choqué.<br>Et si je vous disais que la définition de la table <code>t2</code> ressemble à ce qui suit:</p><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token keyword\">CREATE</span> <span class=\"token keyword\">TABLE</span> t2 <span class=\"token punctuation\">(</span>\n   id <span class=\"token keyword\">VARCHAR</span><span class=\"token punctuation\">(</span><span class=\"token number\">130</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">NOT</span> <span class=\"token boolean\">NULL</span>\n   <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span>\n   <span class=\"token keyword\">PRIMARY</span> <span class=\"token keyword\">KEY</span> <span class=\"token punctuation\">(</span>id<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre><p>En pratique <code>t2.id</code> est toujours une chaîne de 130 caractères et il y a 400<br>millions de tuples dans cette table. Comme vous l’avez déjà probablement compris,<br>il semble étonnant d’avoir <code>p_id CHARACTER</code> pour manipuler <code>id VARCHAR(130)</code>. Pour<br>mémoire, <code>CHARACTER</code> est l’alias de <code>CHAR(1)</code>.</p><p>Notre client utilise cette fonction depuis plusieurs années et il n’a pas eu de<br>problème avec ce code. Néanmoins, notre client m’a dit que la définition de cette<br>fonction ne correspond pas à ce qu’il a écrit: c’était <code>p_id CHARACTER(130)</code> et<br>non <code>CHARACTER</code>.</p><p>Mais que s’est-il donc passé ? Attaquons la pelotte de laine et voyons si Ariane<br>nous est d’un grand secours.</p><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token keyword\">CREATE</span> <span class=\"token keyword\">FUNCTION</span> test<span class=\"token punctuation\">(</span> c <span class=\"token keyword\">character</span><span class=\"token punctuation\">,</span> d <span class=\"token keyword\">character</span> <span class=\"token keyword\">varying</span> <span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">RETURNS</span> void\n<span class=\"token keyword\">LANGUAGE</span> plpgsql\n<span class=\"token keyword\">AS</span> $$\n<span class=\"token keyword\">BEGIN</span>\n  RAISE NOTICE <span class=\"token string\">'c=%, d=%'</span><span class=\"token punctuation\">,</span> c<span class=\"token punctuation\">,</span>d<span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">END</span><span class=\"token punctuation\">;</span>\n$$<span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">SELECT</span> test<span class=\"token punctuation\">(</span> <span class=\"token string\">'123465789'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'987654321'</span> <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nNOTICE:  c<span class=\"token operator\">=</span><span class=\"token number\">123465789</span><span class=\"token punctuation\">,</span> d<span class=\"token operator\">=</span><span class=\"token number\">987654321</span>\n test \n<span class=\"token comment\">------</span>\n \n<span class=\"token punctuation\">(</span><span class=\"token number\">1</span> <span class=\"token keyword\">row</span><span class=\"token punctuation\">)</span></code></pre><p>Voilà un résultat bien intéressant: la chaîne ‘123456789’ n’a pas été réduite à<br>‘1’ (pas de CAST <code>CHAR(1)</code>). Augmentons le niveau de détails:</p><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token keyword\">EXPLAIN</span> <span class=\"token punctuation\">(</span>COSTS <span class=\"token keyword\">OFF</span><span class=\"token punctuation\">,</span><span class=\"token keyword\">ANALYZE</span><span class=\"token punctuation\">,</span>VERBOSE<span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">SELECT</span> test<span class=\"token punctuation\">(</span> <span class=\"token string\">'123465789'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'987654321'</span> <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nNOTICE:  c<span class=\"token operator\">=</span><span class=\"token number\">123465789</span><span class=\"token punctuation\">,</span> d<span class=\"token operator\">=</span><span class=\"token number\">987654321</span>\n                             QUERY <span class=\"token keyword\">PLAN</span>                              \n<span class=\"token comment\">---------------------------------------------------------------------</span>\n Result <span class=\"token punctuation\">(</span>actual <span class=\"token keyword\">time</span><span class=\"token operator\">=</span><span class=\"token number\">0.040</span><span class=\"token punctuation\">.</span><span class=\"token number\">.0</span><span class=\"token number\">.041</span> <span class=\"token keyword\">rows</span><span class=\"token operator\">=</span><span class=\"token number\">1</span> loops<span class=\"token operator\">=</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span>\n   Output: test<span class=\"token punctuation\">(</span><span class=\"token string\">'123465789'</span>::bpchar<span class=\"token punctuation\">,</span> <span class=\"token string\">'987654321'</span>::<span class=\"token keyword\">character</span> <span class=\"token keyword\">varying</span><span class=\"token punctuation\">)</span>\n Planning <span class=\"token keyword\">Time</span>: <span class=\"token number\">0.023</span> ms\n Execution <span class=\"token keyword\">Time</span>: <span class=\"token number\">0.053</span> ms\n<span class=\"token punctuation\">(</span><span class=\"token number\">4</span> <span class=\"token keyword\">rows</span><span class=\"token punctuation\">)</span></code></pre><p>Nous observons un CAST vers <code>bpchar</code>. Pour mémoire, <code>BPCHAR</code> représente une<br>chaîne pouvant contenir 10 485 760 caractères. Il est aussi un alias de<br><code>CHARACTER</code> ce qui explique partiellement le passage de <code>CHARACTER</code> à <code>BPCHAR</code>.</p><p>Explorons une autre facette du problème:</p><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token keyword\">CREATE</span> <span class=\"token keyword\">FUNCTION</span> test<span class=\"token punctuation\">(</span>c <span class=\"token keyword\">character</span><span class=\"token punctuation\">(</span><span class=\"token number\">4</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">RETURNS</span> <span class=\"token keyword\">character</span><span class=\"token punctuation\">(</span><span class=\"token number\">4</span><span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">LANGUAGE</span> <span class=\"token keyword\">sql</span>\n<span class=\"token keyword\">AS</span> $$\n<span class=\"token keyword\">select</span> c<span class=\"token punctuation\">;</span>\n$$<span class=\"token punctuation\">;</span></code></pre><p>Nous avons changé le langage de la fonction pour savoir si le comportement observé<br>est propre à PLpgsql. Les données en entrée et en sortie sont de type <code>CHAR(4)</code>.<br>Comment cela va-t-il se comporter ?</p><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token keyword\">SELECT</span> test<span class=\"token punctuation\">(</span><span class=\"token string\">'123456789'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   test    \n<span class=\"token comment\">-----------</span>\n <span class=\"token number\">123456789</span>\n<span class=\"token punctuation\">(</span><span class=\"token number\">1</span> <span class=\"token keyword\">row</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token keyword\">EXPLAIN</span> VERBOSE <span class=\"token keyword\">SELECT</span> test<span class=\"token punctuation\">(</span><span class=\"token string\">'123456789'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n                QUERY <span class=\"token keyword\">PLAN</span>                 \n<span class=\"token comment\">-------------------------------------------</span>\n Result  <span class=\"token punctuation\">(</span>cost<span class=\"token operator\">=</span><span class=\"token number\">0.00</span><span class=\"token punctuation\">.</span><span class=\"token number\">.0</span><span class=\"token number\">.01</span> <span class=\"token keyword\">rows</span><span class=\"token operator\">=</span><span class=\"token number\">1</span> width<span class=\"token operator\">=</span><span class=\"token number\">32</span><span class=\"token punctuation\">)</span>\n   Output: <span class=\"token string\">'123456789'</span>::bpchar\n<span class=\"token punctuation\">(</span><span class=\"token number\">2</span> <span class=\"token keyword\">rows</span><span class=\"token punctuation\">)</span></code></pre><p>La bonne nouvelle (si si) c’est que le comportement observé est le même dans<br>les deux contextes. En revanche, alors que l’on s’attend à manipuler des données<br>de type <code>CHAR(4)</code>, la fonction manipule des données de taille arbitraire (limitée<br>à ~10M caractères) !!</p><p>Cependant, ne vous précipitez pas dans la mailing list de PostgreSQL pour vous plaindre !</p><p>En fait, ce comportement n’est pas un bug. La <a href=\"https://www.postgresql.org/docs/current/sql-createfunction.html\" rel=\"noopener\">documentation</a> affirme:</p><blockquote><p>“The full SQL type syntax is allowed for declaring a function’s arguments and return value. However, parenthesized type modifiers (e.g., the precision field for type numeric) are discarded by CREATE FUNCTION. Thus for example CREATE FUNCTION foo (varchar(10)) … is exactly the same as CREATE FUNCTION foo (varchar) …”</p></blockquote><p>Ceci explique que <code>CHARACTER(x)</code> devient <code>CHARACTER</code> transformé (par aliasing)<br>en <code>BPCHAR</code> qui n’est pas <code>CHAR(1)</code> mais plutôt <code>VARCHAR(10485760)</code>. Le<br>comportement est maintenant complétement expliqué.</p><p>Attendez une seconde ! L’intention était de traiter des données <code>CHAR(4)</code> pas<br>de taille différente.</p><p>N’y a-t-il pas de solution ? Non, désolé… (à mois que…)</p><p>Plus loin dans la page de la documentation référencée ci-dessus, on peut lire<br>que <code>argtype</code> et <code>rettype</code> peuvent être de type <code>base</code>, <code>composite</code>, <code>domain</code><br>ou même du type d’une table/colonne.</p><p>L’astuce est de créer un type <code>composite</code> ou un <code>domain</code> a utiliser en tant que<br><code>argtype</code> et/ou <code>rettype</code>.</p><p>Voici quelques exemples:</p><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token comment\">-- Works in simple case trick</span>\n<span class=\"token keyword\">SELECT</span> test<span class=\"token punctuation\">(</span> <span class=\"token string\">'12345789'</span>::<span class=\"token keyword\">char</span><span class=\"token punctuation\">(</span><span class=\"token number\">4</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">-- Domain trick</span>\n<span class=\"token keyword\">CREATE</span> DOMAIN c4 <span class=\"token keyword\">AS</span> <span class=\"token keyword\">char</span><span class=\"token punctuation\">(</span><span class=\"token number\">4</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">CREATE</span> <span class=\"token keyword\">FUNCTION</span> test<span class=\"token punctuation\">(</span>param c4<span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">RETURNS</span> c4\n<span class=\"token keyword\">AS</span> $$\n<span class=\"token keyword\">BEGIN</span>\n  RAISE NOTICE <span class=\"token string\">'param=%'</span><span class=\"token punctuation\">,</span> param<span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">RETURN</span> param<span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">END</span><span class=\"token punctuation\">;</span>\n$$ <span class=\"token keyword\">LANGUAGE</span> plpgsql<span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">SELECT</span> test<span class=\"token punctuation\">(</span> <span class=\"token string\">'123456789'</span> <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nERROR:  <span class=\"token keyword\">value</span> too long <span class=\"token keyword\">for</span> <span class=\"token keyword\">type</span> <span class=\"token keyword\">character</span><span class=\"token punctuation\">(</span><span class=\"token number\">4</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token keyword\">SELECT</span> test<span class=\"token punctuation\">(</span> <span class=\"token string\">'123456789'</span>::<span class=\"token keyword\">char</span><span class=\"token punctuation\">(</span><span class=\"token number\">4</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nNOTICE:  param<span class=\"token operator\">=</span><span class=\"token number\">1234</span>\n test \n<span class=\"token comment\">------</span>\n <span class=\"token number\">1234</span>\n<span class=\"token punctuation\">(</span><span class=\"token number\">1</span> <span class=\"token keyword\">row</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token keyword\">SELECT</span> test<span class=\"token punctuation\">(</span> <span class=\"token string\">'123456789'</span>::c4<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nNOTICE:  param<span class=\"token operator\">=</span><span class=\"token number\">1234</span>\n test \n<span class=\"token comment\">------</span>\n <span class=\"token number\">1234</span>\n<span class=\"token punctuation\">(</span><span class=\"token number\">1</span> <span class=\"token keyword\">row</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token keyword\">SELECT</span> pg_typeof<span class=\"token punctuation\">(</span> test<span class=\"token punctuation\">(</span> <span class=\"token string\">'123456789'</span>::<span class=\"token keyword\">char</span><span class=\"token punctuation\">(</span><span class=\"token number\">4</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">)</span> <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nNOTICE:  param<span class=\"token operator\">=</span><span class=\"token number\">1234</span>\n pg_typeof \n<span class=\"token comment\">-----------</span>\n c4\n<span class=\"token punctuation\">(</span><span class=\"token number\">1</span> <span class=\"token keyword\">row</span><span class=\"token punctuation\">)</span></code></pre><p>Le résultat obtenu devrait vous satisfaire.</p><p>Vous n’êtes pas satisfait ?</p><p>Je vous propose une dernière astuce.</p><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token comment\">-- Map a table structure</span>\n<span class=\"token keyword\">CREATE</span> <span class=\"token keyword\">TABLE</span> qq <span class=\"token punctuation\">(</span> c <span class=\"token keyword\">char</span><span class=\"token punctuation\">(</span><span class=\"token number\">4</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">CREATE</span> <span class=\"token keyword\">FUNCTION</span> test<span class=\"token punctuation\">(</span><span class=\"token operator\">IN</span> c qq<span class=\"token punctuation\">,</span> <span class=\"token keyword\">OUT</span> d qq<span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">LANGUAGE</span> <span class=\"token keyword\">sql</span>\n<span class=\"token keyword\">AS</span> $$\n<span class=\"token keyword\">SELECT</span> c<span class=\"token punctuation\">;</span>\n$$<span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">SELECT</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">FROM</span> test<span class=\"token punctuation\">(</span><span class=\"token keyword\">ROW</span><span class=\"token punctuation\">(</span><span class=\"token string\">'12345'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nERROR:  <span class=\"token keyword\">value</span> too long <span class=\"token keyword\">for</span> <span class=\"token keyword\">type</span> <span class=\"token keyword\">character</span><span class=\"token punctuation\">(</span><span class=\"token number\">4</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token keyword\">SELECT</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">from</span> test<span class=\"token punctuation\">(</span><span class=\"token keyword\">ROW</span><span class=\"token punctuation\">(</span><span class=\"token string\">'1234'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  c   \n<span class=\"token comment\">------</span>\n <span class=\"token number\">1234</span></code></pre><p>Hmm, d’accord mais en quoi est-ce différent de l’utilisation d’un <code>domain</code> ?</p><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token comment\">-- Easy Type Alteration</span>\n<span class=\"token keyword\">ALTER</span> <span class=\"token keyword\">TABLE</span> qq <span class=\"token keyword\">ALTER</span> c <span class=\"token keyword\">TYPE</span> <span class=\"token keyword\">char</span><span class=\"token punctuation\">(</span><span class=\"token number\">5</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">SELECT</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">FROM</span> test<span class=\"token punctuation\">(</span> <span class=\"token keyword\">ROW</span><span class=\"token punctuation\">(</span><span class=\"token string\">'12345'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   c   \n<span class=\"token comment\">-------</span>\n <span class=\"token number\">12345</span></code></pre><p>Essayer de modifier un <code>domain</code>, vous verrez comme c’est simple et pas impactant (…).</p><p>L’astuce basée sur la définition de table permet de la flexibilité:</p><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token keyword\">ALTER</span> <span class=\"token keyword\">TABLE</span> qq <span class=\"token keyword\">ADD</span> ee <span class=\"token keyword\">int</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">SELECT</span> test<span class=\"token punctuation\">(</span> <span class=\"token keyword\">ROW</span><span class=\"token punctuation\">(</span><span class=\"token string\">'12345'</span><span class=\"token punctuation\">,</span> <span class=\"token number\">4</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   test   \n<span class=\"token comment\">----------</span>\n <span class=\"token punctuation\">(</span><span class=\"token number\">12345</span><span class=\"token punctuation\">,</span><span class=\"token number\">4</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token keyword\">SELECT</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">FROM</span> test<span class=\"token punctuation\">(</span> <span class=\"token keyword\">ROW</span><span class=\"token punctuation\">(</span><span class=\"token string\">'12345'</span><span class=\"token punctuation\">,</span> <span class=\"token number\">4</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   c   <span class=\"token operator\">|</span> ee \n<span class=\"token comment\">-------+----</span>\n <span class=\"token number\">12345</span> <span class=\"token operator\">|</span>  <span class=\"token number\">4</span></code></pre><p>Nous espérons que vous avez apprécié cet article et que vous avez appris quelque chose de nouveau et d’intéressant.</p></body></html>\n",
      "date_published": "2024-12-02T00:00:00Z"
    }
    ,{
      "id": "https://www.data-bene.io/fr/blog/bienvenue-sur-le-nouveau-blog-data-bene/",
      "url": "https://www.data-bene.io/fr/blog/bienvenue-sur-le-nouveau-blog-data-bene/",
      "title": "Bienvenue sur le nouveau blog de Data Bene",
      "content_html": "\n<html><head></head><body><h2 id=\"explorer-postgresql-lopen-source-et-linnovation\"><a href=\"https://www.data-bene.io/fr/blog/bienvenue-sur-le-nouveau-blog-data-bene/#explorer-postgresql-lopen-source-et-linnovation\" class=\"heading-anchor\">Explorer PostgreSQL, l’Open Source et l’Innovation</a></h2><p>Chez Data Bene, nous sommes ravis de vous présenter la nouvelle version de notre blog, où nous plongerons dans les sujets liés à PostgreSQL, aux technologies open source et aux tendances émergentes du marché. Grâce à cette mise à jour, nous avons pour ambition de vous offrir un contenu riche en analyses techniques, en actualités du secteur et en études de cas inspirantes.</p><p>Partisans convaincus des solutions open source, nous croyons fermement que PostgreSQL est un moteur d’innovation et d’efficacité pour les entreprises modernes. À travers nos articles et nos tutoriels, nous visons à permettre à nos lecteurs d’exploiter pleinement le potentiel de PostgreSQL. Nous aborderons nos fonctionnalités préférées et partagerons les dernières avancées de cet écosystème incontournable, des sujets qui, selon nous, vous aideront à tirer le meilleur parti de ce puissant système de gestion de bases de données relationnelles.</p><p>Dans un environnement technologique en constante mutation, l’open source s’impose comme le symbole de la collaboration, de l’innovation et du développement communautaire.</p><p>Pour cette raison, dans notre blog, nous explorerons :</p><ol class=\"list\"><li>les outils open-source qui font partie de l’écosystème PostgreSQL,</li><li>comment améliorer et soutenir la collaboration open-source, et</li><li>des projets pour continuer à progresser dans les développements qui façonnent l’avenir des technologies ouvertes tout en évitant le verrouillage par les fournisseurs.</li></ol><p>Avec des années d’expérience auprès d’une gamme variée d’entreprises, des startups émergentes aux entreprises mondiales, nous avons vu de première main comment les organisations innovantes utilisent PostgreSQL pour assurer leur succès. Notre blog mettra en vedette non seulement des idées d’entrepreneurs et de leaders technologiques partageant leurs expériences, mais aussi des articles approfondis de nos propres expertes et experts PostgreSQL. Ils discuteront de leurs fonctionnalités PostgreSQL préférées, des outils natifs, des défis rencontrés et de la manière dont ils les ont surmontés, offrant ainsi une perspective technique unique sur les défis du monde réel.</p><p>Nous explorerons également les tendances émergentes et les nouvelles technologies qui façonnent l’avenir de PostgreSQL, offrant un aperçu de la manière dont les startups et les entreprises établies naviguent dans l’évolution rapide de la gestion des données. Que ce soit par des interviews de fondateurs ou des analyses de projets innovants, nous mettrons en lumière comment PostgreSQL continue d’être un acteur clé de l’innovation dans le monde technologique d’aujourd’hui.</p><p>Enfin, chez Data Bene, la durabilité n’est pas qu’un mot à la mode — c’est une valeur fondamentale qui guide chacune de nos actions. Alors que nous nous engageons dans de nouvelles initiatives de développement et explorons les technologies de pointe, nous nous engageons à minimiser notre empreinte environnementale et à promouvoir des pratiques éco-responsables. De l’optimisation de l’efficacité des logiciels à la réduction de la consommation d’énergie, nous nous engageons à construire un avenir plus durable, ligne de code après ligne de code. Par conséquent, certains des articles que nous publierons mettront en avant ces pratiques et ouvriront la discussion sur la durabilité dans les pratiques de développement de PostgreSQL.</p><p>Nous vous invitons à nous rejoindre dans cette aventure passionnante d’exploration, de découverte et d’innovation. Que vous soyez un passionné de PostgreSQL, un défenseur de l’open source, un amateur de startups, un développeur expérimenté ou simplement curieux, il y en aura pour tous les goûts dans notre blog ! Alors, mettez cette page en favori, <a href=\"https://fr.linkedin.com/company/data-bene\" rel=\"noopener\">suivez-nous sur LinkedIn</a> et gardez un œil sur notre prochaine newsletter. Où que vous nous suiviez, vous pourrez rester informé de nos mises à jour régulières remplies de précieuses idées et d’inspiration.</p><p>Merci de faire partie de notre communauté. Ensemble, continuons à grandir, apprendre et réussir.</p></body></html>\n",
      "date_published": "2024-09-25T00:00:00Z"
    }
    ,{
      "id": "https://www.data-bene.io/fr/blog/data-bene-partenaire-du-pgday-paris-2023/",
      "url": "https://www.data-bene.io/fr/blog/data-bene-partenaire-du-pgday-paris-2023/",
      "title": "Data Bene partenaire du pgDay Paris 2023",
      "content_html": "\n<html><head></head><body><ul class=\"list\"><li></li></ul><p>Comme chaque année Data Bene participe activement aux pgDays qui, nouveauté de cette année, seront sur deux jours. Évènement devenu incontournable pour tous les adeptes de PostgreSQL! Data Bene est “Partner” de cet événement qui vous donne la possibilité de vous former, de partager les expériences et de découvrir les dernières avancées, fonctionnalités de la base de données relationnelles open source.</p><p>Dans sa volonté de contribution, Data Bene participe aussi à la journée du 22 mars pour délivrer des Tutoriels (En Français):</p><p>Le matin, Frédéric Delacourt présentera «Tout ce que vous avez toujours voulu savoir sur les Pools de Connexions (sans jamais oser le demander)», de 9h à 12h15.</p><p>L’après-midi, ce sera au tour de Cédric Villemain avec «CREATE EXTENSION, la vôtre de préférence», de 13h45 à 17h.</p><p>Nous sommes ravis de pouvoir vous y accueillir. Vous trouverez le détails des formations sur l’agenda des 2 jours, et vous pourrez vous enregistrer sur la page inscription.</p><p>En espérant vous y voir nombreux !</p><p>L’équipe de Data Bene.</p></body></html>\n",
      "date_published": "2023-03-14T00:00:00Z"
    }
    ,{
      "id": "https://www.data-bene.io/fr/blog/data-bene-partenaire-du-meetup-postgresql-geneve-cern-2022/",
      "url": "https://www.data-bene.io/fr/blog/data-bene-partenaire-du-meetup-postgresql-geneve-cern-2022/",
      "title": "Data Bene contribue au Meetup PostgreSQL@CERN 2023",
      "content_html": "\n<html><head></head><body><p>Data Bene est co-sponsor avec le CERN du Meetup organisé par le groupe d’utilisateurs de<br>PostgreSQL de Genève, le vendredi 13 Janvier après midi au CERN à Genève. Cédric et Hélène<br>serons heureux de vous y accueillir ou de vous compter parmi nous in situ ou via<br>le webcast: <a href=\"https://webcast.web.cern.ch/event/i1221200\" rel=\"noopener\">https://webcast.web.cern.ch/event/i1221200</a></p><p>Nous y animerons une conférence sur Citus Data: Base de donnée distribuée sans<br>complexe.</p></body></html>\n",
      "date_published": "2023-01-11T00:00:00Z"
    }
    ,{
      "id": "https://www.data-bene.io/fr/blog/data-bene-partenaire-du-pgday-paris-2022/",
      "url": "https://www.data-bene.io/fr/blog/data-bene-partenaire-du-pgday-paris-2022/",
      "title": "Data Bene partenaire du pgDay Paris 2022",
      "content_html": "\n<html><head></head><body><p>Data Bene sera présent tout au long de la journée de 24 mars 2022 en temps que «Partner Sponsor» pour vous acceuillir à LA conférence de la communauté en France. Nous y animerons une conférence sur le partitionnement.</p></body></html>\n",
      "date_published": "2022-03-23T00:00:00Z"
    }
    
  ]
}
