Loxodata
Actualités des organisations
Loxodata
|
PostgreSQL et Debezium |
|||||||
---|---|---|---|---|---|---|---|---|
Bourgogne-Franche-Comté Publié le mardi 03 juin 2025 10h30 Importé le mardi 03 juin 2025 13h05 |
Dans cet article, nous allons regarder comment connecter PostgreSQL vers d’autres applications avec Debezium, dans le cadre d’un cluster Patroni assurant la haute disponibilité. Debezium repose sur un ensemble de services distribués conçus pour capturer les changements survenants dans vos bases de données afin que d’autres applications puissent consulter ces changements et les consommer, communément appelé CDC pour change data capture. DebeziumDebezium propose de capturer les flux d’évènements depuis vos bases de données permettant aux applications de répondre à des changements survenant au niveau des lignes de tables sur vos bases de données. Debezium repose sur le broker de messages Apache Kafka et fournit un ensemble de connecteurs sources pour Kafka Connect par type de sources, par exemple pour PostgreSQL. Le connecteur enregistre l’historique des changements sur une base de données en acquittant les changements au fil de l’eau et en sauvegardant chaque évènement dans un topic Kakfa (file de messages), et la position dans les journaux de transactions (WAL). Le connecteur Debezium pour PostgreSQL se base sur le décodage logique pour récupérer les changements commités dans les journaux de transactions et un plugin de sortie pour mettre en forme les données. PostgreSQL ne conserve pas tout l’historique des journaux de transactions, car les fichiers WAL sont recyclés quand nécessaire par PostgreSQL. Debezium doit donc gèrer lui même l’historique des lignes, et donc l’initialiser. Ceci se fait à la première connexion par une sauvegarde de l’état de la base de données (snapshot). Pour ce faire, le connecteur suit les étapes suivantes:
Ensuite, le connecteur entre dans sa boucle d’envoi d’évènements consommés depuis PostgreSQL. Le connecteur convertit chaque changement en évènement create, update ou delete définit par Debezium, avec son LSN et les enregistre dans Kakfa Connect, qui à son tour les transmets à un topic Kakfa. Kakfa Connect stocke en parallèle le LSN actuel afin de repartir de ce point lors de l’arrêt de Kakfa Connect. À l’image de cette première architecture basée sur Kakfa Connect et Apache Kakfa, il existe deux autres types d’architecture disponible:
Mise en place avec PostgreSQLLe connecteur Debezium pour PostgreSQL prend en charge deux plugins de sortie: pgoutput qui est le plugin par défaut utilisé avec la réplication logique ou decoderbufs basé sur le format Protobuf et maintenu par la communauté Debezium. Pour cet exemple, nous utilisons le plugin decoderbufs. Nous ne détaillons pas la mise en place de Debezium et ses services associés, mais uniquement la mise en place côté PostgreSQL. Pour Debezium, il convient de se référer à la documentation. Il faut tout d’abord installer le plugin decoderbufs sur votre serveur via le système de paquet approprié. Sous RedHat, on peut par exemple utiliser la commande dnf pour installer le paquet pour la version 14 de Postgresql en utilisant le dépôt du PGDG: dnf install postgres-decoderbufs_14.x86_64On vérifie l’installation du paquet avec: dnf list installed postgres-decoderbufs_14.x86_64 Installed Packages postgres-decoderbufs_14.x86_64 3.0.2-1PGDG.rhel9Puis on modifie la configuration de PostgreSQL via la commande patronictl edit-config pour charger le plugin et autoriser le décodage logique via le paramètre wal_level à logical. cat | patronictl -c /etc/patroni/patroni.yml edit-config --apply - <<_EOF_ postgresql: parameters: shared_preload_libraries: decoderbufs wal_level: logical _EOF_Et on redémarre les instances pour prise en compte des paramètres avec la commande patronictl restart car Les paramètres wal_level et shared_preload_libraries exige un redémarrage de l’instance PostgreSQL. patronictl -c /etc/patroni/config.yml restart --force loxodemoIl peut être nécessaire d’affiner les paramètres suivants selon votre cas d’usage:
Nous créons maintenant le rôle de réplication dédié au connecteur Debezium et ajoutons les permissions nécessaires. demo=# CREATE ROLE debezium_replication LOGIN REPLICATION WITH PASSWORD '<redacted>' CREATE ROLE demo=# GRANT SELECT ON ALL TABLES IN SCHEMA public TO debezium_replication; GRANT demo=# ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO debezium_replication; ALTER DEFAULT PRIVILEGESOn ajoute l’utilisateur créé dans le fichier .pgpass si ce dernier est utilisé. Il faut ensuite adapter le fichier pg_hba.conf pour autoriser le connecteur Debezium à se connecter à l’instance PostgreSQL. host demo debezium_replication <ip du connecteur ou plage autorisée> scram-sha-256Nous créons à présent la publication portant sur tous les schémas de la base de données, et créons manuellement le slot de réplication. Il est possible de limiter les tables publiées dans la commande CREATE PUBLICATION ou de définir un schéma en particulier. demo=# CREATE PUBLICATION pub_con_to_debezium FOR ALL TABLES; CREATE PUBLICATION demo=# SELECT * FROM pg_create_logical_replication_slot('logical_pub_con_to_debezium_slot', 'decoderbufs'); INFO: Exiting startup callback slot_name | lsn ----------------------------------+------------ logical_pub_con_to_debezium_slot | D/7901ACD8 (1 row)Nous mettons à jour la configuration de PostgreSQL via Patroni pour déclarer l’utilisation du slot de réplication logique et rechargeons la configuration. cat | patronictl -c /etc/patroni/patroni.yml edit-config --apply - <<_EOF_ postgresql: use_slots: true slots: logical_pub_con_to_debezium_slot: database: demo plugin: decoderbufs type: logical _EOF_SupervisionUne fois la configuration en place, il est nécessaire de surveiller la consommation des WAL et l’état des slots de réplication. En effet, si le connecteur venait à s’arrêter de consommer les données du slot de réplication, le paramètre confirmed_flush_lsn n’étant pas mis à jour, alors PostgreSQL va accumuler les fichiers WAL nécessaires au slot de réplication en attendant une reprise éventuelle. Ceci peut conduire à la saturation du système de fichiers et entraîner dans le pire des cas l’arrêt de PostgreSQL. On peut utiliser des gardes fous comme le paramètre max_slot_wal_keep_size pour limiter la quantité de fichiers WAL conservée par un slot de réplication. Pour surveiller l’activité des slots de réplication, nous utilisons la vue pg_replication_slots (ici en version 14 de PostgreSQL). demo=# select * from pg_replication_slots; -[ RECORD 1 ]-------+--------------------------------- slot_name | logical_pub_con_to_debezium_slot plugin | decoderbufs slot_type | logical datoid | 16437 database | demo temporary | f active | t active_pid | 2132668 xmin | catalog_xmin | 134506175 restart_lsn | 55/99983378 confirmed_flush_lsn | 55/999873C0 wal_status | reserved safe_wal_size | two_phase | f
On vérifie que les paramètres confirmed_flush_lsn et restart_lsn soient bien incrémentés. On peut calculer en utilisant cette même vue la quantité de WAL retenue et le lag vers le connecteur. demo=# SELECT slot_name, active, confirmed_flush_lsn, pg_current_wal_lsn(), pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS retained_walsize, pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), confirmed_flush_lsn)) AS subscriber_lag FROM pg_replication_slots; slot_name | active | confirmed_flush_lsn | pg_current_wal_lsn | retained_walsize | subscriber_lag ----------------------------------+--------+---------------------+--------------------+------------------+---------------- logical_pub_con_to_debezium_slot | t | 20D4/EEAB53A0 | 20D4/FB3A6000 | 239 MB | 201 MB (1 rows)
Configuration du connecteur DebeziumAfin de configurer le connecteur Debezium source pour PostgreSQL, il est nécessaire de fournir au minimum les éléments suivants dans un fichier json que l’on peut nommer pg-example-connector.json: { "name":"pg-example-connector", "config":{ "connector.class":"io.debezium.connector.postgresql.PostgresConnector", "database.hostname":"pgdeb01", "database.port":"5437", "database.user":"debezium_replication", "database.password":"<redacted>", "database.dbname":"demo", "plugin.name":"decoderbufs", "slot.name":"logical_pub_con_to_debezium_slot", "publication.name":"pub_con_to_debezium", } }La liste complète des paramètres de configuration du connecteur Debezium pour PostgreSQL est disponible dans la documentation de Debezium. L'API REST de Kafka Connect permet d’enregistrer de nouveaux connecteurs et de vérifier le status de ces derniers. Une fois enregistré, le connecteur est actif. Côté Kakfa, il est possible d’utiliser l’utilitaire bin/kafka-console-consumer.sh pour s’abonner à un topic donné et visualiser les messages reçus depuis le connecteur PostgreSQL. Pour le reste des opérations de Apache Kafka, je vous renvoie à la documentation complète de ce dernier. Crédits photo: Callum Blacoe |
|||||||
Loxodata
|
PostgreSQL 17.5 et autres correctifs |
|||||||
Bourgogne-Franche-Comté Publié le mardi 13 mai 2025 12h01 Importé le mardi 13 mai 2025 13h05 |
Le PGDG (PostgreSQL Global Development Group) a publié une mise à jour de toutes les versions supportées de PostgreSQL, incluant 17.5, 16.9, 15.13, 14.18 et 13.21. Cette publication corrige également une vulnérabilité de sécurité et plus de 60 bogues reportés dans les mois précédents. Fin du support de la version 13 de PostgreSQLLa version 13 de PostgreSQL ne recevra plus de correctifs à partir du 13 novembre 2025. Il est donc recommandé de mettre à jour vers une version majeure vos instances en production. Se référer à la note de versions pour plus d’informations. Problèmes de sécurité
Lors de l’utilisation de l’encodage GB18030 (encodage officiel chinois), il est possible à un attaquant d’effectuer une lecture au-delà du tampon de validation de cet encodage. Cette lecture provoque un arrêt du processus et induit un déni de service temporaire. Cette vulnérabilité concerne le serveur de bases de données PotgreSQL et la bibliothèque libpq. Les versions antérieures à PostgreSQL 17.5, 16.9, 15.13, 14.18, et 13.21 sont affectées. Corrections de bogues et améliorationsCette mise à jour corrige plus de 60 bogues ayant été signalés durant les mois précédents. Les problèmes ci-dessous concernent PostgreSQL 17. Certains de ces problèmes peuvent aussi concerner d’autres versions de PostgreSQL. Les correctifs sont:
Cette version met également à jour les fichiers de données de fuseaux horaires avec la version 2025b de tzdata pour les changements de loi de l’heure d’été au Chili, ainsi que des corrections historiques pour l’Iran. En outre, un nouveau fuseau horaire America/Coyhaique a été créé pour la région d’Aysén au Chili, afin de tenir compte du fait qu’elle passe à UTC-03 tout au long de l’année, ce qui diverge d'America/Santiago. Mise à jourToutes les publications de mises à jour de PostgreSQL sont cumulatives. Comme pour les autres mises à jour mineures, il n’est pas nécessaire d’extraire et de recharger les bases de données ni d’utiliser pg_upgrade pour appliquer cette mise à jour; il suffit simplement d’arrêter PostgreSQL et de mettre à jour les binaires. Les utilisateurs ayant sauté une ou plusieurs mises à jour peuvent avoir besoin d’étapes additionnelles après la mise à jour. Les notes de publication des versions précédentes fournissent les détails. Pour plus de détails, se référer à la note de publication de versions. LiensSi vous avez des corrections ou suggestions sur cette annonce de publication, merci de les envoyer à la mailing liste publique pgsql-www@lists.postgresql.org. |
|||||||
Loxodata
|
PostgreSQL 18 bêta 1 |
|||||||
Bourgogne-Franche-Comté Publié le mardi 13 mai 2025 12h00 Importé le mardi 13 mai 2025 13h05 |
Cette version 18 de PostgreSQL promet de nombreuses améliorations de performances avec notamment le sous-système d’entrées/sorties asynchrones pour les lectures, la conservation des statistiques lors d’une mise à jour de version majeure, l’ajout du support de l’authentification OAuth 2.0 et la dépréciation de md5, l’ajout de nombreuses statistiques par défaut lors d’un EXPLAIN ANALYZE et d’autres fonctionnalités encore autour de la réplication logique. Vous pouvez retrouver la documentation pour la version 18 et les notes de publications. PostgreSQL 18 Bêta 1 publiéeLe PostgreSQL Global Development Group annonce la disponibilité de la première bêta de PostgreSQL 18 en téléchargement. Cette publication contient un aperçu des fonctionnalités qui seront disponibles dans la version finale de PostgreSQL 18. Des modifications peuvent toutefois intervenir d’ici là. Vous pouvez trouver des informations sur toutes les fonctionnalités et les changements de PostgreSQL 18 dans les notes de version Dans l’esprit de la communauté open source PostgreSQL, nous vous encourageons fortement à tester les nouvelles fonctionnalités de PostgreSQL dans vos systèmes de base de données. Ceci afin de nous aider à éliminer les bogues et autres problèmes qui pourraient exister. Bien que nous ne vous conseillons pas de faire fonctionner PostgreSQL 18 Bêta 1 dans vos environnements de production, nous vous encourageons à trouver des moyens de faire fonctionner votre charge applicative typique avec cette publication bêta. Vos tests et vos commentaires aideront la communauté à s’assurer que PostgreSQL 18 respecte nos standards de stabilité et fiablité. Vous pouvez également vous renseigner sur notre processus de beta testing et comment y contribuer. Principales fonctionnalités de PostgreSQL 18Vous trouverez ci-dessous les principales fonctionnalités planifiées pour PostgreSQL 18. Cette liste n’est pas exhaustive: pour la liste complète des fonctionnalités, se référer à la note de publication. Optimisation des performancesPostgreSQL 18 introduit un sous-système d’entrées/sorties asynchrones (AIO). Ce nouveau sous-système permet d’augmenter le débit des E/S et de masquer leur latence. Sous Linux, io_uring peut être utilisé pour les AIO, une implantation basée sur un worker est disponible pour toutes les plateformes. Cette version initiale prend en charge les lectures du système de fichiers telles que les lectures séquentielles, les bitmap heap scan et les vacuum, avec des tests montrant une amélioration des performances de 2 à 3 fois plus rapides. Ces gains de performance s’étendent aux optimisations des requêtes et aux nouvelles fonctionnalités d’indexation. PostgreSQL 18 ajoute le support de l’utilisation des recherches skip scan sur les index multicolonnes B-tree, ce qui peut résulter en des temps d’exécution plus rapides pour les requêtes qui omettent une condition = sur un ou plusieurs préfixe de colonnes de l’index. Cette version inclut également des optimisations pour les clauses WHERE qui contiennent des instructions OR et IN afin de mieux utiliser les récentes améliorations d’indexation, ce qui peut également améliorer les performances des requêtes. Il y a aussi de nombreuses améliorations de performance dans la façon dont PostgreSQL planifie et exécute les jointures de tables, depuis l’amélioration de la performance globale des jointures de type hash jusqu’à la possibilité pour les jointures de type merge d’utiliser des tris incrémentaux. Il existe une variété d’autres fonctionnalités de PostgreSQL 18 qui améliorent les performances pour d’autres opérations de requête et de maintenance. PostgreSQL 18 supporte maintenant les créations parallèles pour les index GIN, qui sont couramment utilisés pour la recherche sur les données JSON et plein texte. Cette version permet également de définir des clés de partition et des vues matérialisées avec des index uniques qui ne sont pas de type B-tree. PostgreSQL 18 améliore également les performances globales de verrouillage pour les requêtes qui accèdent à de nombreuses relations, et ajoute plusieurs améliorations aux requêtes sur les tables partitionnées, y compris un meilleur support du pruning et des jointures. PostgreSQL 18 a également amélioré les performances du traitement de texte, y compris l’accélération des fonctions upper/lower et une nouvelle collation intégrée PG_UNICODE_FAST. Expérience des mises à jours de versions majeuresAvant PostgreSQL 18, une étape importante après avoir effectué une mise à jour majeure était d’exécuter la commande ANALYZE pour générer des statistiques, ce qui est un composant critique pour aider PostgreSQL à sélectionner le plan de requête le plus efficace. En fonction de la taille et de l’activité globale d’un cluster PostgreSQL, ce processus pouvait prendre beaucoup de temps et avoir un impact potentiel sur les performances des requêtes jusqu’à ce que le processus soit terminé. PostgreSQL 18 introduit la possibilité de conserver les statistiques du planificateur lors d’une mise à jour majeure, ce qui permet à un cluster mis à jour d’atteindre ses performances attendues plus rapidement une fois qu’il est disponible. De plus, pg_upgrade, l’utilitaire utilisé pour faciliter la mise à jour d’une version majeure, a ajouté plusieurs améliorations de performance pour aider à accélérer les mises à jour avec de nombreux objets, tels que les tables et les séquences. Cette version permet également à pg_upgrade de faire ses vérifications en parallèle en fonction des paramètres de l’option --jobs, et ajoute également l’option --swap, qui échange les répertoires de mise à niveau au lieu de copier, cloner ou lier des fichiers. Expérience développeurPostgreSQL 18 introduit les colonnes virtuelles générées qui calculent les valeurs des colonnes pendant l’exécution de la requête, au lieu de les stocker. C’est maintenant l’option par défaut pour les colonnes générées. De plus, les colonnes générées stockées peuvent maintenant être répliquées logiquement. Cette version ajoute la possibilité d’accéder à la fois aux valeurs précédentes (OLD) et actuelles (NEW) dans la clause RETURNING pour les commandes INSERT, UPDATE, DELETE et MERGE. De plus, PostgreSQL 18 ajoute le support de la génération d'UUIDv7 à travers la fonction uuidv7(), permettant la génération des UUIDs aléatoires qui sont ordonnés en fonction de l’horodatage pour supporter de meilleures stratégies de cache (cette version ajoute également uuidv4() comme alias pour gen_rand_uuuid). Maintenant, avec PostgreSQL 18, vous pouvez faire des comparaisons LIKE sur du texte qui utilise une collation non déterministe, ce qui rend plus simple la recherche de motifs complexes. De plus, cette version introduit CASEFOLD pour faciliter les correspondances insensibles à la casse. Cette version ajoute également des contraintes temporelles, ou des contraintes sur des plages, pour les contraintes PRIMARY KEY et UNIQUE à l’aide de la clause WITHOUT OVERLAPS, et pour les contraintes FOREIGN KEY à l’aide de la clause PERIOD. SécuritéPostgreSQL 18 introduit l’authentification oauth, qui permet aux utilisateurs de s’authentifier en utilisant les mécanismes OAuth 2.0 supportés par l’utilisation d’extensions PostgreSQL. De plus, PostgreSQL 18 ajoute plusieurs fonctionnalités pour valider et renforcer le comportement du mode FIPS, et ajoute également ssl_tls13_ciphers pour permettre aux utilisateurs de configurer les suites de chiffrement TLS v1.3 que le serveur peut utiliser. Cette version déprécie l’authentification par mot de passe md5 en faveur de l’utilisation de l’authentification SCRAM qui a été ajoutée pour la première fois dans PostgreSQL 10. L’authentification md5 sera complètement supprimée dans une prochaine version majeure. De plus, PostgreSQL 18 ajoute le support de l’authentification SCRAM passthrough avec postgres_fdw et dblink lors de l’authentification d’instances PostgreSQL distantes. SupervisionPostgreSQL 18 ajoute plus de détails à l’utilitaire EXPLAIN, qui fournit des informations sur l’exécution du plan de requête, et depuis cette version montre automatiquement combien de buffers (l’unité fondamentale de stockage des données, par défaut 8KB) sont accédés lors de l’exécution d'EXPLAIN ANALYZE. En outre, EXPLAIN ANALYZE indique désormais le nombre de lectures d’index au cours d’un scan d’index, et EXPLAIN ANALYZE VERBOSE inclut des statistiques sur l’utilisation CPU, les WAL et la lecture moyenne. Cette version inclut également des informations sur le temps total passé en vacuum et analyse de table dans pg_stat_all_tables, et montre maintenant des statistiques par connexion sur l’utilisation des E/S et des WAL. PostgreSQL 18 fournit également plus d’informations sur les conflits d’écriture qui se produisent durant la réplication logique, et affiche ces informations à la fois dans les journaux et dans la vue pg_stat_subscription_stats. Autres fonctionnalitésDepuis PostgreSQL 18, les sommes de contrôle des données, qui sont utilisées pour valider l’intégrité des données stockées, sont maintenant activées par défaut sur les nouveaux clusters PostgreSQL. Vous pouvez choisir de désactiver ce comportement en utilisant la commande initdb --no-data-checksums. Notez que cela peut nécessiter des changements dans vos scripts de mise à jour. De plus, de nouveaux comportements sont disponibles dans plusieurs fonctionnalités de contraintes. Tout d’abord, les contraintes de clé étrangère et de vérification peuvent être définies comme NOT ENFORCED et, inversement, rendues exécutoires. De plus, les contraintes NOT NULL préservent maintenant leurs noms comme l’exige le standard SQL, supportent les clauses NOT VALID et NO INHERIT, et se comportent maintenant de manière plus cohérente avec l’héritage. pg_createsubscriber supporte maintenant le drapeau --all pour que vous puissiez créer des réplicas logiques pour toutes les bases de données d’une instance avec une seule commande. De plus, PostgreSQL 18 vous permet de créer la définition du schéma d’une table étrangère en utilisant la définition d’une table locale en utilisant la commande CREATE FOREIGN TABLE ... LIKE. PostgreSQL 18 introduit également une nouvelle version (3.2) du protocole de communication, qui est la première nouvelle version du protocole depuis PostgreSQL 7.4 (2003). libpq utilise toujours la version 3.0 par défaut en attendant que les clients (par exemple, les pilotes, les poolers, les proxies) ajoutent le support de la nouvelle version du protocole. Fonctionnalités supplémentairesDe nombreuses autres fonctionnalités et améliorations ont été ajoutées à PostgreSQL. En fonction des cas d’usages, leur importance peut paraître plus ou moins grande que celles mentionnées ci-dessus. Vous pouvez consulter les notes de publications pour une liste complète des nouveautés et changements: https://www.postgresql.org/docs/18/release-18.html Tests pour le débogage et la compatibilitéLa stabilité de chaque publication de PostgreSQL dépend de vous, la communauté. En testant la version à venir avec votre charge et vos outils de tests, vous pourrez nous aider à trouver les bogues et régressions avant la publication de PostgreSQL 18. Étant donné qu’il s’agit d’une version bêta, des changements mineurs dans le comportement de la base de données, des détails et des APIs sont toujours possibles. Vos retours et tests aideront à déterminer les ajustements finaux des nouvelles fonctionnalités. La qualité des tests aide à déterminer le moment de la publication finale. Une liste des problèmes ouverts est publiquement disponible dans le wiki de PostgreSQL. Vous pouvez rapporter des bogues en utilisant le formulaire présent sur le site web de PostgreSQL: https://www.postgresql.org/account/submitbug/. Planning BêtaIl s’agit de la première publication bêta de la version 18. Le projet PostgreSQL publiera autant de bêtas que cela est nécessaire pour tester. Celles-ci seront suivies par une ou plusieurs publications de versions candidates, jusqu’à la publication de la version finale vers septembre/octobre 2025. Pour plus d’information, veuillez consulter la page Beta Testing. Liens
Crédits photo: Carlos Gonzalez |
|||||||
Loxodata
|
POSETTE 2025 |
|||||||
Bourgogne-Franche-Comté Publié le jeudi 24 avril 2025 16h00 Importé le jeudi 24 avril 2025 21h05 |
Le programme 2025Pour sa quatrième année, l’évènement virtuel POSETTE revient du 10 au 12 juin 2025. Cette conférence virtuelle et gratuite proposera durant ces trois jours 42 présentations de 45 orateurs différents, réparties en quatres diffusions en direct. Il sera possible de rejoindre un serveur Discord afin de poser des questions aux orateurs et de discuter avec les autres participants. Le programme complet est disponible sur le site de la conférence et le planning des diffusions: Cette année, la conférence proposera une keynote de Bruce Momjian autour de l’IA et des bases de données et de Charles Feddersen sur les contributions de Microsoft pour PostgreSQL sur l’année 2025. Crédits photo: Microsoft |
|||||||
Loxodata
|
Retour sur le pgDay Paris 2025 |
|||||||
Bourgogne-Franche-Comté Publié le mardi 01 avril 2025 09h00 Importé le mardi 01 avril 2025 21h04 |
Le 20 mars 2025 s’est tenue la 9e édition du pgDay Paris 2025. Cette édition s’est déroulée au sein de l’espace Saint Martin, dans le 3e arrondissement de Paris, qui dispose d’un bel auditorium. LOXODATA était, cette année encore, sponsor «partner» de l’évènement. Nous avions un stand, ce qui nous a permis des échanges intéressants avec les auditeurs de cette édition. Cette année encore, 2 salles de conférences étaient dédiées à l’événement. La seconde était majoritairement attribuée à des conférences courtes faites par des sponsors. Le programme complet est sur le site du pgDay Paris 2025 Les conférencesLe programme de la journée de conférences comportait onze sessions en anglais, et une en français, réparties entre l’auditorium et une autre salle plus petite. S’ajoutait également une session de conférences éclair. Parmi toutes ces conférences, on pouvait retrouver plusieurs présentations non techniques. Tuning community parameters: Hosting PostgreSQL events that performAprès l’introduction faite par Vik Fearing, la keynote d’ouverture s’est déroulée dans l’auditorium. Ellyne Phneah nous présenta les clés de l’organisation d’évènements communautaires PostgreSQL, en s’appuyant sur l’expérience
du M-PUG (Malmö PostgreSQL User Group) et des conférences PostgreSQL.
Une première partie insiste sur l’importance des communautés et des évènements PostgreSQL, et comment les faire reconnaître
officiellement par la communauté. Puis, elle nous exposa l’importance dans la sélection des sujets, les formats engageants, la
logistique et l’implication d’orateurs. Professional PostgreSQL monitoring made easyAprès cette conférence, deux choix se présentaient. Maintenir un inventaire de l’écosystème communautaire autour de PostgreSQLDans le même temps, dans la salle Karnak, Jérôme Desroziers (Orange France) et Stéphane Schildknecht (LOXODATA) présentèrent en
français comment «maintenir un inventaire de l’écosystème communautaire autour de PostgreSQL». Cette présentation avait pour but
d’introduire un nouveau projet libre de catalogue des outils et extensions open source autour de PostgreSQL. Full-Text-Search Explained from A to Z with French FoodAvant la pause déjeuner, Matt Cornillon nous ouvrit l’appétit avec une conférence sur le full text search sur le thème de la
nourriture française. Dear Azure Database for PostgreSQL, can you automate my index?Tout d’abord Emmanuel Deletang nous à présenté une fonctionnalité d’«Azure Database for PostgreSQL - Flexible Server» qui facilite l’optimisation des index. Cet assistant intégré surveille, analyse et ajuste en continu les index pour améliorer les performances. Distributed vector database with aidb and PGDNous n’avons malheureusement pas assisté à cette conférence. C’est pourtant toujours un plaisir de voir Boriss Mejías, qui est un excellent orateur. Lightning Talks!Après la pause méridienne, ce fut le moment des conférences éclair, dans l’auditorium. 7 personnes se sont succédées pour nous présenter 6 sujets, chacun en moins de 5 minutes chrono. L’animation était réalisée par Magnus Hagander.
Why PostgreSQL people should really care about Kafka and Debezium?Après ce moment un peu plus léger, une autre conférence par Dirk Krautschick nous a intéressés à Kafka et Debezium. Le constat de
départ est que le métier de DBA change, et désormais, beaucoup de choses se basent sur des flux. Waiting for PostgreSQL 18En parallèle dans le deuxième salle, Frederic Delacourt donnait des détails pour vous aider à prévoir les migrations et anticiper
ce qui se passera à l’avenir. PostgreSQL and NodeJs as a Core Feature of Backend for FrontendViktoriia Hrechukha nous a présenté 2 dérivés de nodejs, et la manière de se connecter à PostgreSQL depuis nextjs. Dans l’optique d’un front end, les différentes manières de rendre une page ont été évoquées (SSR, CSR, SSG, ISR, mixte). My Journey in PostgreSQL bug fixingBertrand Drouvot nous à partagé son expérience sur quelques corrections de bogues et a approfondi la façon de les reproduire, la tentative initiale de correction et le correctif final. Explore the role of PostgreSQL in GitLab ecosystemHana Litavská, chercheuse doctorante à l’université de Pragues, s’est intéressée à la manière dont PostgreSQL est utilisé avec GitLab. En utilisant une méthode de reverse engineering, elle a cherché les stratégies et techniques utilisées par GitLab pour optimiser ses interactions avec la base de données. GitLab n’est pas un sujet très simple puisqu’il existe plusieurs types d’environnements possibles selon les clients. Puis, Vik Fearing conclua la journée avec le mot de la fin. ConclusionCe pgday Paris a fait la place à des conférences plus accessibles et moins centrées sur PostgreSQL, explorant des méthodes de travail et des outils liés à PostgreSQL. Le public était un peu moins nombreux que les années précédentes, et le passage à deux salles de conférences de l’année dernière différait légèrement cette année, puisque la deuxième salle était majoritairement occupée par les sponsors. Espérons que l’année prochaine, le dixième pgday Paris aura bien lieu et rassemblera de nouveau un public nombreux. Nous espérons vous y retrouver! |
|||||||
Loxodata
|
PostgreSQL Extension Day 2025 |
|||||||
Bourgogne-Franche-Comté Publié le lundi 17 mars 2025 09h30 Importé le lundi 17 mars 2025 13h04 |
PostgreSQL Extension Day 2025Le 12 mai 2025 se tiendra l’événement gratuit PostgreSQL Extension Day à Montréal, soit la veille de la conférence PostgreSQL PGConf.dev qui se tiendra pour sa part du 13 au 15 mai. Cette conférence n’est toutefois pas affiliée à la PGConf.dev. Ce rassemblement a pour but de réunir tous les acteurs qui contribuent et utilisent les extensions de PostgreSQL constituant un écosystème de plusieurs centaines de projets: près de 400 actuellement. Le PostgreSQL Extension Day est organisé par le groupe Postgres Extension Developers Coalition. Le CFP est ouvert jusqu’au 1er avril 2025, et les inscriptions sont ouvertes par ici. |
|||||||
Loxodata
|
L'extension pg_trgm |
|||||||
Bourgogne-Franche-Comté Publié le vendredi 07 mars 2025 09h20 Importé le vendredi 07 mars 2025 13h04 |
L’extension pg_trgmPrésentationL’extension pg_trgm (trigrammes) est fournie dans la distribution standard de PostgreSQL. Elle est présente dans /contrib et s’installe simplement dans une base de données: loxodata_text=# CREATE EXTENSION IF NOT EXISTS pg_trgm; CREATE EXTENSIONCette extension permet de décomposer une chaîne de caractères en succession de sous-chaînes de 3 caractères (trigrammes), afin de permettre des recherches sur une sous-chaîne, ou bien des recherches de similarité entre chaînes de caractères. FonctionnementJeu d’essaiDans le cadre de cette présentation, je me suis constitué une table d’un million de lignes, laquelle contient un champ family contenant un nom de famille parmi les 1000 plus fréquent en France, et dont la fréquence dans la table est semblable à celle de la population française: loxodata_text=# \dS my_datas Table "public.my_datas" Column | Type | Collation | Nullable | Default -------------+--------+-----------+----------+-------------------------------------- id | bigint | | not null | nextval('my_datas_id_seq'::regclass) random_text | text | | | family | text | | | Indexes: "idx_test_id" btree (id) loxodata_text=# SELECT count(1) FROM my_datas; count --------- 1000204 (1 row) loxodata_text=# SELECT * FROM my_datas LIMIT 5; id | random_text | family --------+--------------------------------------+--------- 211685 | 94376bb6-3655-4a65-b61a-8dbec927c5e5 | GRANGER 211686 | 7f9f8a34-13f2-4459-bd2c-e4b90a7eca9b | LE ROUX 211687 | 526549b3-13fe-4aae-87c1-4a5480cf6898 | FUCHS 211688 | 1acbdde8-b4cd-4bf8-957c-84adf1c6cf1c | BRUNET 211689 | 77cd8645-bfe8-471c-a118-3dbe507d8e8f | LAMBERT (5 rows)DécompositionOn peut visualiser la décomposition en trigrammes avec la fonction show_trgm() : loxodata_text=# SELECT show_trgm('GRANGER'); show_trgm ----------------------------------------- {" g"," gr",ang,"er ",ger,gra,nge,ran} (1 row)SimilaritéLa fonction similarity() permet de tester la similarité entre deux chaînes de caractères. Le résultat est un score entre 0 et 1. Zéro indique qu’il n’y a aucun trigramme en commun entre les deux chaînes, tandis que 1 indique que les deux chaînes sont identiques. On peut ainsi tester la similarité entre deux noms de famille: loxodata_text=# select similarity('GRANGER','BRUNET'); similarity ------------ 0 (1 row) loxodata_text=# select similarity('GRANGER','GRANGE'); similarity ------------ 0.6666667 (1 row) loxodata_text=# select similarity('GRANGER','GRANIER'); similarity ------------ 0.45454547 (1 row) loxodata_text=# select similarity('GRANGER','LEGRAND'); similarity ------------ 0.14285715 (1 row)L’opérateur booléen de similarité entre deux chaînes est% : loxodata_text=# select 'GRANGER' % 'GRANIER'; ?column? ---------- t (1 row) loxodata_text=# select 'GRANGER' % 'LEGRAND'; ?column? ---------- f (1 row)L’opérateur booléen retourne True si le score de similarité excède une limite fixée par défaut à 0.3. La limite courante peut être consultée avec la fonction show_limit() : loxodata_text=# select show_limit(); show_limit ------------ 0.3 (1 row)Et cette limite peut être modifiée au niveau de la session avec la fonction set_limit(). Ainsi, si on passe le seuil à 0.1, ‘GRANGER’ et ‘LEGRAND’ sont désormais considérés comme similaires: loxodata_text=# select set_limit(0.1); set_limit ----------- 0.1 (1 row) loxodata_text=# select 'GRANGER' % 'LEGRAND'; ?column? ---------- t (1 row)Cette limite peut être configurée au niveau du cluster avec le paramètre pg_trgm.similarity_threshold. Indexation et performancesL’indexation BTREE classiqueLes champs TEXT peuvent être indexés classiquement avec un index BTREE: loxodata_text=# CREATE INDEX idx_test ON my_datas(family text_pattern_ops); CREATE INDEXCela permet de trouver rapidement des chaînes de caractères ou des débuts de chaînes de caractères: loxodata_text=# EXPLAIN ANALYZE SELECT id FROM my_datas WHERE family = 'GRANGER'; QUERY PLAN --------------------------------------------------------------------------------------------------------------------- Bitmap Heap Scan on my_datas (cost=10.09..2289.04 rows=731 width=8) (actual time=0.101..0.584 rows=658 loops=1) Recheck Cond: (family = 'GRANGER'::text) Heap Blocks: exact=637 -> Bitmap Index Scan on idx_test (cost=0.00..9.91 rows=731 width=0) (actual time=0.047..0.047 rows=658 loops=1) Index Cond: (family = 'GRANGER'::text) Planning Time: 0.120 ms Execution Time: 0.612 ms (7 rows) loxodata_text=# EXPLAIN ANALYZE SELECT id FROM my_datas WHERE family like 'GRAN%'; QUERY PLAN ----------------------------------------------------------------------------------------------------------------------- Index Scan using idx_test on my_datas (cost=0.42..8.45 rows=66 width=8) (actual time=0.024..2.121 rows=3692 loops=1) Index Cond: ((family ~>=~ 'GRAN'::text) AND (family ~<~ 'GRAO'::text)) Filter: (family ~~ 'GRAN%'::text) Planning Time: 0.137 ms Execution Time: 2.234 ms (5 rows)Cependant un tel index se révèle inutile lorsqu’on ne connaît pas le début de la chaîne recherchée. Dance ce cas on bascule sur un Seq Scan malgré la présence de l’index: loxodata_text=# EXPLAIN ANALYZE SELECT id FROM my_datas WHERE family like '%ANGER'; QUERY PLAN --------------------------------------------------------------------------------------------------------------------------- Gather (cost=1000.00..17185.70 rows=6643 width=8) (actual time=0.196..36.796 rows=2585 loops=1) Workers Planned: 2 Workers Launched: 2 -> Parallel Seq Scan on my_datas (cost=0.00..15521.40 rows=2768 width=8) (actual time=0.027..33.117 rows=862 loops=3) Filter: (family ~~ '%ANGER'::text) Rows Removed by Filter: 332540 Planning Time: 0.071 ms Execution Time: 36.894 ms (8 rows)Indexation des trigrammesIl est possible d’indexer les vecteurs de trigrammes avec un index GIN: loxodata_text=# CREATE INDEX idx_test_trgm ON my_datas USING GIN(family gin_trgm_ops); CREATE INDEXLa recherche sur la fin de chaîne de caractères se fait maintenant en utilisant l’index nouvellement créé: loxodata_text=# EXPLAIN ANALYZE SELECT id FROM my_datas WHERE family like '%ANGER'; QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------- Bitmap Heap Scan on my_datas (cost=94.35..9754.04 rows=6643 width=8) (actual time=1.422..3.197 rows=2585 loops=1) Recheck Cond: (family ~~ '%ANGER'::text) Heap Blocks: exact=2292 -> Bitmap Index Scan on idx_test_trgm (cost=0.00..92.69 rows=6643 width=0) (actual time=1.193..1.194 rows=2585 loops=1) Index Cond: (family ~~ '%ANGER'::text) Planning Time: 0.085 ms Execution Time: 3.282 ms (7 rows)Nous pouvons maintenant effectuer une recherche de similarité: loxodata_text=# EXPLAIN ANALYZE SELECT DISTINCT family FROM my_datas WHERE family% 'GRANGER'; QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------- Unique (cost=370.28..370.61 rows=64 width=7) (actual time=19.476..19.867 rows=6 loops=1) -> Sort (cost=370.28..370.45 rows=66 width=7) (actual time=19.474..19.632 rows=4284 loops=1) Sort Key: family Sort Method: quicksort Memory: 264kB -> Bitmap Heap Scan on my_datas (cost=119.31..368.29 rows=66 width=7) (actual time=7.737..18.771 rows=4284 loops=1) Recheck Cond: (family% 'GRANGER'::text) Rows Removed by Index Recheck: 3468 Heap Blocks: exact=5458 -> Bitmap Index Scan on idx_test_trgm (cost=0.00..119.29 rows=66 width=0) (actual time=7.173..7.173 rows=7752 loops=1) Index Cond: (family% 'GRANGER'::text) Planning Time: 0.297 ms Execution Time: 19.887 ms (12 rows) loxodata_text=# SELECT DISTINCT family FROM my_datas WHERE family% 'GRANGER'; family ---------- GRAND GRANGE GRANGER GRANIER GRAS LAGRANGE (6 rows)Cette recherche par similarité peut être utile, votre serviteur en sait quelque chose avec son patronyme qui comporte un ‘B’ muet et qui entraîne souvent moultes confusions lorsque je dois épeler mon nom, et qui est donc écrit souvent approximativement: loxodata_text=# SELECT DISTINCT family FROM my_datas WHERE family% 'LEFEBVRE'; family ---------- LEFEBVRE LEFEVRE LEFEUVRE (3 rows)PerformancesOn peut voir que sur une recherche d’égalité, ou bien sur une recherche de début de chaîne, c’est l’index B-Tree qui est préféré par le planner: loxodata_text=# EXPLAIN ANALYZE SELECT family FROM my_datas WHERE family = 'LEFEBVRE'; QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------- Index Only Scan using idx_test on my_datas (cost=0.42..1370.94 rows=3801 width=7) (actual time=0.018..0.488 rows=4312 loops=1) Index Cond: (family = 'LEFEBVRE'::text) Heap Fetches: 399 Planning Time: 0.340 ms Execution Time: 0.615 ms (5 rows) loxodata_text=# EXPLAIN ANALYZE SELECT family FROM my_datas WHERE family like 'LEFEBVRE%'; QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------- Index Only Scan using idx_test on my_datas (cost=0.42..1389.95 rows=3867 width=7) (actual time=0.010..0.729 rows=4312 loops=1) Index Cond: ((family ~>=~ 'LEFEBVRE'::text) AND (family ~<~ 'LEFEBVRF'::text)) Filter: (family ~~ 'LEFEBVRE%'::text) Heap Fetches: 399 Planning Time: 0.165 ms Execution Time: 0.877 ms (6 rows) loxodata_text=# drop index idx_test; DROP INDEXIl est cependant important de noter que si l’index B-Tree est préféré sur la recherche en début de chaîne ( LIKE 'xxxx%' ) c’est parce que la classe d’opérateurs text_pattern_ops a été utilisée lors de la création de l’index. Si nous créons un index B-Tree sans cette classe d’opérateurs, il sera préféré pour une recherche d’égalité, mais pas pour une recherche de début de chaîne du fait des problèmes complexes liés aux LOCALES des différentes langues: loxodata_text=# CREATE INDEX idx_test ON my_datas(family); CREATE INDEX loxodata_text=# EXPLAIN ANALYZE SELECT family FROM my_datas WHERE family like 'LEFEBVRE%'; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------ Bitmap Heap Scan on my_datas (cost=139.26..7724.28 rows=3867 width=7) (actual time=2.370..5.048 rows=4312 loops=1) Recheck Cond: (family ~~ 'LEFEBVRE%'::text) Heap Blocks: exact=3544 -> Bitmap Index Scan on idx_test_trgm (cost=0.00..138.29 rows=3867 width=0) (actual time=2.000..2.000 rows=4312 loops=1) Index Cond: (family ~~ 'LEFEBVRE%'::text) Planning Time: 0.162 ms Execution Time: 5.179 ms (7 rows)Si nous supprimons définitivement l’index B-Tree, on voit que l’index sur les trigrammes est utilisé efficacement pour une recherche d’égalité (seulement après PG v13) mais pas aussi efficacement qu’avec l’index B-Tree (coût estimé 7666 vs 1370). Cependant ce coût est remarquablement constant que la recherche se fasse sur une égalité, un début de chaîne (LIKE 'xxx%') ou une recherche sur une sous-chaîne (LIKE '%xxx%'). loxodata_text=# EXPLAIN ANALYZE SELECT family FROM my_datas WHERE family = 'LEFEBVRE'; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------ Bitmap Heap Scan on my_datas (cost=151.72..7666.35 rows=3801 width=7) (actual time=3.331..6.085 rows=4312 loops=1) Recheck Cond: (family = 'LEFEBVRE'::text) Heap Blocks: exact=3544 -> Bitmap Index Scan on idx_test_trgm (cost=0.00..150.77 rows=3801 width=0) (actual time=2.961..2.962 rows=4312 loops=1) Index Cond: (family = 'LEFEBVRE'::text) Planning Time: 0.095 ms Execution Time: 6.298 ms (7 rows) loxodata_text=# EXPLAIN ANALYZE SELECT family FROM my_datas WHERE family like 'LEFEBVRE%'; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------ Bitmap Heap Scan on my_datas (cost=139.26..7724.28 rows=3867 width=7) (actual time=2.632..5.366 rows=4312 loops=1) Recheck Cond: (family ~~ 'LEFEBVRE%'::text) Heap Blocks: exact=3544 -> Bitmap Index Scan on idx_test_trgm (cost=0.00..138.29 rows=3867 width=0) (actual time=2.263..2.263 rows=4312 loops=1) Index Cond: (family ~~ 'LEFEBVRE%'::text) Planning Time: 0.075 ms Execution Time: 5.584 ms (7 rows) loxodata_text=# EXPLAIN ANALYZE SELECT family FROM my_datas WHERE family like '%LEFEBVRE%'; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------ Bitmap Heap Scan on my_datas (cost=109.52..7694.54 rows=3867 width=7) (actual time=1.628..4.402 rows=4312 loops=1) Recheck Cond: (family ~~ '%LEFEBVRE%'::text) Heap Blocks: exact=3544 -> Bitmap Index Scan on idx_test_trgm (cost=0.00..108.55 rows=3867 width=0) (actual time=1.260..1.260 rows=4312 loops=1) Index Cond: (family ~~ '%LEFEBVRE%'::text) Planning Time: 0.078 ms Execution Time: 4.603 ms (7 rows)Conclusion
|
|||||||
Loxodata
|
Retour sur la PG Conf Europe 2024 |
|||||||
Bourgogne-Franche-Comté Publié le lundi 24 février 2025 15h10 Importé le lundi 24 février 2025 21h06 |
Retour sur la PG Conf Europe 2024Cette année, la PostgreSQL Conference Europe 2024 s’est déroulée à Athènes, en Grèce, à quelques hectomètres de l’acropole. À nouveau, un record d’affluence est battu cette année avec 779 participants, ce qui en fait l’évènement PostgreSQL le plus important au monde. La liste des conférences est disponible sur le site de l’évènement: https://2024.pgconf.eu/. Les supports de présentations, ainsi que les enregistrements vidéos sont également mis à disposition. La conférence d’ouverture est donnée par Stacey Haysler. Le sujet abordé est celui du coût de la licence PostgreSQL. Cette dernière étant gratuite, elle demande une implication des différents acteurs pour que le projet puisse fonctionner et demeurer robuste et pérenne. Les conférences sont ensuite réparties dans différentes salles, avec 4 conférences simultanées, dont une réservée aux sponsors. Nous résumons ici nos notes à propos des présentations auxquelles nous avons assisté. PerformanceAndres Freund nous explique les particularités de NUMA, qui est une architecture d’accès à la mémoire, ce qui a des conséquences pour les processeurs, et donc les logiciels qui s’en servent. Quels sont les problèmes rencontrés dans le contexte de l’utilisation de PostgreSQL? Cette présentation est complexe, mais détaillée et permet à l’auditoire de mieux comprendre le comportement global des systèmes, tout en ouvrant vers des optimisations possibles de PostgreSQL. Les orateurs Thomas Munro & Nazir Bilal Yavuz détaillent un point important concernant les performances des lectures et écritures de données (I/O) : après un historique des solutions, ils expliquent ce que sont les solutions modernes telles que les Streaming I/O et que peut apporter le patch AIO qui est en cours de développement. Rafael Thofehrn Castro nous présente des extensions et patchs pour suivre les plans d’exécutions à la volée dans une instance PostgreSQL. C’est bluffant, malheureusement rien n’est disponible publiquement. Louise Leinweber détaille de façon claire et précise ce que sont les statistiques sur les données dans PostgreSQL, comment elles sont utilisées dans PostgreSQL et quels leviers nous avons pour agir. Denzil Ribeiro évoque l’outillage nécessaire à la supervision d’une instance PostgreSQL dans le cloud, en particulier tout ce qui est spécifique aux environnements clouds, très utile lorsqu’on vient d’environnements dits “on-premise”. Stacey Haysler et Karen Jex utilisent quelques points emblématiques des problèmes souvent rencontrés par les utilisateurs de PostgreSQL pour évoquer les bonnes ou mauvaises pratiques et certains anti-patterns connus. Robert Treat évoque avec humour ses mésaventures avec les vacuums et les ID de transactions, et les améliorations apportées depuis dans PostgreSQL 17. Ryan Booz évoque un outil très utile en ce qui concerne la gestion de la performance: le partitionnement des tables, ses différentes possibilités et cas d’usage, jusqu’aux extensions que sont TimescaleDB et Citus. High availibilityBoriss Mejías détaille le fonctionnement d’une réplication active-active, avec toutes les notions, plus ou moins complexes, qui permettent de bien comprendre les contraintes qu’imposent ce type de réplication. Michael Banck expose de façon pratique et claire le fonctionnement de Patroni, avec quelques éléments pertinents à retenir, correspondant à son expérience. Julian Markwort compare les différents gestionnaires de connexions entre eux. Quelles sont les différentes questions qui se posent pour adopter un tel outil, et pourquoi faut-il choisir pgBouncer? Euler Taveira présente le développement qu’il a mené dans PostgreSQL pour intégré l’outil pg_createsubscriber qui permet de convertir une réplication physique en réplication logique, accélérant ainsi la création d’un réplica logique. KubernetesKaren Jex explique le fonctionnement de Kubernetes et l’utilisation de l’opérateur Crunchy Postgres, et comment son fonctionnement s’articule avec le rôle et les responsabilités d’un administrateur de bases de données. Adam Wright évoque le lien entre Kubernetes et PostgreSQL: les opérateurs! Différents opérateurs pour PostgreSQL existent et ne sont pas strictement équivalents, ce qui nécessite une compréhension de chacun d’entre eux de la part de l’administrateur de bases de données pour les adopter: sécurité, réseau, sauvegarde, stockage, extension. David Pech fait le retour d’expérience d’une migration d’instance PostgreSQL depuis des machines virtuelles vers un cluster Kubernetes. Le choix de l’opérateur Kubernetes est un point important de la démarche. Après avoir fait tomber quelques mythes autour de Kubernetes, l’orateur détaille de plan de travail pour adopter la solution. Dave Pitts et Derk Van Veen introduisent les concepts de haute disponibilité de PostgreSQL par le jeu, ce qui est toujours une bonne manière d’apprendre. Intelligence artificielleJonathan Katz parle de l’extension pgvector, qui est une possibilité offerte aux utilisateurs de PostgreSQL de vectoriser des données et de faire des recherches par approximation. Grant Fritchey se demande si les prompts d’IA sont de bons outils pour les DBA? Quelles sont les différentes tâches du DBA qui pourraient bénéficier de l’aide d’un assistant conversationnel? SécuritéLætitia Avrot évoque l’ensemble des fonctionnalités liées aux permissions dans PostgreSQL: rôle, groupe, privilèges, Row Level Security, privilèges par défaut. Taras Kloba détaille un sujet très important, quoique parfois trop négligé: comment protéger PostgreSQL contre les attaques. Des mises à jour de sécurité à la gestion de l’authentification en passant par la protection des données, cette présentation fait la liste des points à retenir en termes de sécurité. Peter Eisentraut fait le tour des besoins et solutions de chiffrement de données disponibles avec PostgreSQL. AutresLe modèle actuel de snapshot, qui autorise la visibilité des enregistrements, est maintenant vieux de plus de vingt ans: quel modèle peut-il le remplacer, en prenant en compte la croissance de la concurrence d’accès. L’orateur évoque alors les notions de Commit Sequence Number ou d’un modèle hybride. Christoph Berg explique en détail le fonctionnement de PostgreSQL lorsqu’on lui demande de supprimer un enregistrement, et ce qu’il est possible de faire pour retrouver cet enregistrement avec l’extension pg_dirtyread ou la commande pg_waldump. Dans tous les cas, faites des sauvegardes! Yugo Nagata présente l’extension pg_ivm qui permet de créer des vues matérialisées incrémentales, qui sont donc mises à jour rapidement, contrairement aux vues matérialisées existantes dans PostgreSQL qui nécessitent une régénération entière. |
|||||||
Loxodata
|
PostgreSQL 17.4 et autres correctifs |
|||||||
Bourgogne-Franche-Comté Publié le jeudi 20 février 2025 15h30 Importé le jeudi 20 février 2025 21h07 |
Le PGDG (PostgreSQL Global Development Group) a publié une mise à jour de toutes les versions supportées de PostgreSQL, incluant 17.4, 16.8, 15.12, 14.17 et 13.20. Pour la liste complète des changements, se référer à la note de publication de versions. Corrections de bogues et améliorationsLes problèmes ci-dessous concernent PostgreSQL 17. Certains de ces problèmes peuvent aussi concerner d’autres versions de PostgreSQL. Les correctifs sont:
Mise à jourToutes les publications de mises à jour de PostgreSQL sont cumulatives. Comme pour les autres mises à jour mineures, il n’est pas nécessaire d’extraire et de recharger les bases de données ni d’utiliser pg_upgrade pour appliquer cette mise à jour; il suffit simplement d’arrêter PostgreSQL et de mettre à jour les binaires. Les utilisateurs ayant sauté une ou plusieurs mises à jour peuvent avoir besoin d’étapes additionnelles après la mise à jour. Les notes de publication des versions précédentes fournissent les détails. Pour plus de détails, se référer à la note de publication de versions. LiensSi vous avez des corrections ou suggestions sur cette annonce de publication, merci de les envoyer à la mailing liste publique pgsql-www@lists.postgresql.org. |
|||||||
Loxodata
|
PostgreSQL 17.3 et autres correctifs |
|||||||
Bourgogne-Franche-Comté Publié le vendredi 14 février 2025 16h00 Importé le vendredi 14 février 2025 21h04 |
Le PGDG (PostgreSQL Global Development Group) a publié une mise à jour de toutes les versions supportées de PostgreSQL, incluant 17.3, 16.7, 15.11, 14.16, 13.19. Cette publication corrige également une vulnérabilité de sécurité et plus de 70 bogues reportés dans les mois précédents. Cependant, le PGDG a annoncé mettre à disposition le 20 février prochain un correctif suite à l’introduction d’une régression sur cette mise à jour. Il est recommandé de ne pas procéder à cette mise à jour, mais d’attendre la version 17.4. Problèmes de sécurité
Une neutralisation inadéquate d’une syntaxe avec guillemets dans les fonctions de libpq PQescapeLiteral(), PQescapeIdentifier(), PQescapeString() et PQescapeStringConn() permet de faire de l’injection SQL dans certains cas d’usage. Spécifiquement, l’injection SQL requiert à l’application d’utiliser le résultat de fonction pour construite l’entrée de psql, le terminal interactif de PostgreSQL. De même, une neutralisation inadéquate d’une syntaxe avec guillemets dans les programmes utilitaires de PostgreSQL en ligne de commande permet à une source d’arguments à ces commandes en ligne d’effectuer de l’injection SQL lorsque le paramètre client_encoding est BIG5 et server_encoding est soit EUC_TW soit MULE_INTERNAL. Les versions antérieures à PostgreSQL 17.3, 16.7, 15.11, 14.16 et 13.19 sont affectées. Le projet PostgreSQL remercie Stephen Fewer, Principal Security Researcher, Rapid7 pour avoir signalé ce problème.
Corrections de bogues et améliorationsCette mise à jour corrige plus de 70 bogues ayant été reportés durant les mois précédents. Les problèmes ci-dessous concernent PostgreSQL 17. Certains de ces problèmes peuvent aussi concerner d’autres versions de PostgreSQL. Les correctifs sont:
Cette publication met aussi à jour les fichiers de fuseaux horaires avec la publication de tzdata 2025a pour les changements de lois DST au Paraguay, plus des corrections historiques pour les Philippines. Mise à jourToutes les publications de mises à jour de PostgreSQL sont cumulatives. Comme pour les autres mises à jour mineures, il n’est pas nécessaire d’extraire et de recharger les bases de données ni d’utiliser pg_upgrade pour appliquer cette mise à jour; il suffit simplement d’arrêter PostgreSQL et de mettre à jour les binaires. Les utilisateurs ayant sauté une ou plusieurs mises à jour peuvent avoir besoin d’étapes additionnelles après la mise à jour. Les notes de publication des versions précédentes fournissent les détails. Pour plus de détails, se référer à la note de publication de versions. LiensSi vous avez des corrections ou suggestions sur cette annonce de publication, merci de les envoyer à la mailing liste publique pgsql-www@lists.postgresql.org. |
|||||||
Loxodata
|
Correctif hors cycle pour PostgreSQL |
|||||||
Bourgogne-Franche-Comté Publié le vendredi 14 février 2025 09h00 Importé le vendredi 14 février 2025 13h04 |
Le PGDG prévoit une livraison hors cycle pour le 20 février 2025 afin de corriger une régression introduite sur la mise à jour du 13 février 2025 portant sur les versions mineures: 17.3, 16.7, 15.11, 14.16 et 13.19. Dans cette mise à jour, vous retrouverez des correctifs pour les versions supportées (17.4, 16.8, 15.12, 14.17, 13.20). Bien que ces correctifs puissent ne pas impacter tous les utilisateurs de PostgreSQL, le PGDG a préféré adresser le problème au plus tôt et ne pas attendre la prochaine échéance prévue le 8 mai 2025. Le correctif de sécurité CVE-2025-1094, traitant d’une vulnérabilité dans la librairie libpq de PostgreSQL, a introduit une régression portant sur la gestion des chaînes de caractères (“C string”) terminée par un caractère non nul. L’erreur pourrait être visible en fonction de comment un client PostgreSQL a implémenté ce comportement, et peut ne pas impacter tous les drivers PostgreSQL. Par précaution, le PGDG a avancé le cycle de mise à jour. Si vous êtes impacté par ce problème, il est recommandé d’attendre la sortie des versions 17.4, 16.8, 15.12, 14.17 et 13.29 avant de mettre à jour PostgreSQL. |
|||||||
Loxodata
|
pgwatch 3 |
|||||||
Bourgogne-Franche-Comté Publié le lundi 03 février 2025 15h30 Importé le lundi 03 février 2025 21h04 |
SupervisionL’outil pgwatch est l’un des outils les plus populaires pour la supervision des instances PostgreSQL. Le projet a été initié par la société Cybertec pour ses propres besoins. Initialement en version 2, pgwatch2 a été réécrit récemment en version 3. Pavlo Golub est en charge du projet chez Cybertec. Cette version 3 propose les mêmes fonctionnalités éprouvées de la version 2 avec quelques nouveautés, notamment le stockage en parallèle vers plusieurs stockages, l’utilisation de l’API v3 de Etcd, factorisation du code et dépréciation de certains types de stockage (InfluxDB par exemple), mise à jour des versions de certains composants tels que Grafana ou les images Docker mis à disposition. Pour rappel, pgwatch se base sur un collecteur écrit en go qui vient récupérer une liste de métriques prédéfinies, mais extensibles à souhait afin de récupérer des statistiques sur vos instances PostgreSQL et le système (moyennant l’utilisation de l’extension PL/Python) quelque soit leur nombre avec le minimum d’impact. Le stockage des métriques s’effectue sur PostgreSQL, mais il est aussi possible de choisir TimescaleDB, Prometheus ou des fichiers JSON. Les tableaux de bord fournis sont utilisables dans l’outil Grafana, ce qui permet de les personnaliser finement, de créer des alertes, et de gérer finement les accès aux différents tableaux et données collectées. pgwatch permet aussi de récupérer les statistiques des outils tels que PgBouncer, Patroni, Pgpool-II, Prometheus, parser les logs de PostgreSQL, ou de récupérer des statistiques depuis des services managés de PostreSQL chez divers fournisseurs de solution cloud (AWS, Azure, Google). L’architecture de pgwatch est très modulaire et permet de s’adapter à votre infrastructure et à tous vos cas d’usage ou presque. Quelques nouveautésRemote SinksUne des nouveautés de la version 3 de pgwatch est le découplage de la partie stockage. L’introduction des remote sinks avec la possibilité d’utiliser l’interface (basée sur RPC) mise à disposition pour implémenter un type de stockage particulier pour y pousser les métriques de pgwatch. Mais aussi, la possibilité de disposer en parallèle de plusieurs stockages des métriques, par exemple vers une base de données et un fichier JSON. EtcdAutre grosse nouveauté, c’est le passage à la version 3 de l’API de etcd. En effet, jusqu’à la version 3.3 de etcd, l’API par défaut était la version 2. Le protocole de la version 2 n’étant pas compatible avec la version 3 de ce dernier. Lors de l’utilisation d’un cluster Patroni et de la découverte automatique des noeuds, pgwatch se base sur le protocole d'etcd. Pour cette raison, pgwatch en version 3 utilise la version 3.5 de etcd afin d’utiliser le protocole version 3 de l’API etcd. Le protocole version 2 n’étant pas compatible avec le protocole en version 3, les clés/valeurs de la version 2 ne pourront être lues avec la version 3. Il faudra migrer en utilisant la procédure de migration donnée par etcd ici. Côté patroni, la migration repose sur le changement dans le fichier de configuration de la version de etcd en indiquant etcd3. La documentation de pgwatch est disponible ici pour la version 3. Migration vers pgwatch3La question de la migration de pgwatch2 vers pgwatch3 se pose. Dans la documentation actuelle, rien n’y fait référence. Mais après discussion avec Pavlo Golub, il existe un utilitaire de conversion pour convertir des métriques personnalisées au format utilisé par pgwatch2 vers celui de pgwatch3. Il est ainsi possible de récupérer vos anciennes métriques personnalisées pour les convertir dans le format utilisé par pgwatch avec un unique fichier .yaml: go run convert_metrics.go --src /home/projects/pgwatch2/pgwatch2/metrics/ --dst /tmp/metrics.yamlRéférences |
|||||||
Loxodata
|
Ecosystème opensource PostgreSQL |
|||||||
Bourgogne-Franche-Comté Publié le mardi 28 janvier 2025 11h00 Importé le mardi 28 janvier 2025 13h04 |
L’écosystème PostgreSQLUne collaboration entre ORANGE et LOXODATA a initié le projet libre pg-ecosystem. Ce projet se présente comme un catalogue des outils et extensions libres autour de PostgreSQL afin de répondre à deux questions:
De ces deux questions ont découlé les travaux autour d’une étude sur les outils et extensions libres. Nous avons défini des critères d’évaluation les plus objectifs possibles: vivacité du projet, perennité des contributions, adoption par la communauté… Le projet s’est structuré en catalogue, proposant une fiche par projet (produit). Chaque fiche décrit le produit succinctement et inclut les attributs suivants:
Les attributs du projet pourraient être amenés à évoluer, en fonction des retours que nous aurons. Le projet pg-ecosystem est publié sous licence CC-BY-SA et est publié en anglais. Le catalogue est rendu disponible via le portail pg-ecosystem. Les contributions sont acceptées et bienvenues sur Gitlab pg-ecosystem. Le projet a été présenté à la dernière édition du Capitole du Libre 2024 dont vous pouvez retrouver la présentation: Construction d’un catalogue de l’écosystème Open Source de PostgreSQL. |
|||||||
Loxodata
|
OpenSource Experience 2024 - Les vidéos sont en ligne |
|||||||
Bourgogne-Franche-Comté Publié le vendredi 24 janvier 2025 10h00 Importé le vendredi 24 janvier 2025 21h04 |
La présentation de LOXODATA à l’OpenSource Experience 2024 est en ligneCôté conférences, nous avons parlé de le sécurisation des accès aux bases de données, une présentation très rapide en 20 minutes d’un vaste sujet. Le support est disponible Sécurisons PostgreSQL . L’OSXP a publié les vidéos des conférences données pendant les deux jours. Vous pouvez retrouver la captation de notre présentation «Sécurisons les accès à PostgreSQL» sur la chaîne Youtube de l’événement. |
|||||||
Loxodata
|
L'extension pgvector |
|||||||
Bourgogne-Franche-Comté Publié le vendredi 17 janvier 2025 11h00 Importé le vendredi 17 janvier 2025 13h05 |
Ces deux dernières années, on aura noté l’engouement autour de l’IA, du machine learning et de son accessibilité via les plateformes telles que OpenAI. La communauté PostgreSQL s’est penchée dessus aussi afin de rendre PostgreSQL attractif comme moteur de bases de données vectorielles, grâce à son extensibilité, notamment depuis la sortie de l’extension pg_vector. IntroductionL’extension pgvector créée par Andrew Kane, et initiée en avril 2021, vient de connaître un élan de popularité depuis deux ans, surtout à la vue de l’engouement des travaux autour de l’IA et du machine learning, et de fait des vecteurs. Pourtant les principes mathématiques et les algorithmes utilisés dans le machine learning et l’IA existent depuis plusieurs décennies. Ce qui a changé c’est l’accessibilité de ces derniers et la mise à disposition des données issues de ces algorithmes très rapidement, ce qui implique de pouvoir stocker les données vectorielles au plus près des applications. Pour revenir à pgvector, cette extension permet à PostgreSQL de stocker des données vectorielles grâce à un nouveau type de données spécialisé et indexable, et d’effectuer des recherches vectorielles de type K-NN (K nearest-neighbor) ou ANN (aproximate nearest-neighbor) en proposant désormais deux types d’index: IVFFlat et HNSW. Jonathan Katz a écrit une série d’articles sur pgvector, auquel il contribue activement, et notamment cet article: Vectors are the new JSON in PostgreSQL où il y fait le parallèle entre le support du JSON par PostgreSQL et les vecteurs. Jonathan Katz nous rappelle comment PostgreSQL a fait le pari de supporter le format JSON/JSONB, à la base un format d’échange, pour répondre aux besoins des développeurs d’applications afin de stocker des données au format JSON et de pouvoir les requêter efficacement. La communauté PostgreSQL continue d’ailleurs d’implémenter le standard SQL/JSON et pousse à son adoption. La version 17 de PostgreSQL fournit par exemple de nouvelles fonctions JSON et un nouveau constructeur JSON_TABLE(). Ce qui s’est passé pour PostgreSQL avec JSON est en train de se reproduire avec les vecteurs: le besoin de stocker et rechercher des vecteurs, donnant l’occasion à PostgreSQL de devenir une base de données vectorielles avec toutes les fonctionnalités que PostgreSQL offre déjà. ExtensibilitéUne des forces de PostgreSQL est son extensibilité éprouvée et permet d’ajouter de nouvelles fonctionnalités sans toucher au code principal. L’écosystème des extensions est immense. Vous pouvez retrouver une liste exhaustive des extensions sur PGXN. Parmi les plus connues, on peut citer pg_stat_statements pour surveiller les statistiques d’exécution des requêtes SQL, postgis pour gérer les données géospatiales ou encore timescaledb pour gérer les séries temporelles. Parmi les vues disponibles sous PostgreSQL pour lister les extensions, vous pouvez utiliser les vues [pg_available_extensions](https://www.postgresql.org/docs/current/view-pg-available-extensions.html ou [pg_available_extension_versions](https://www.postgresql.org/docs/current/, ou la vue pg_extension. Bases de données vectoriellesAvant de rentrer dans le détail de l’implémentation de pgvector, nous allons rappeler ce qu’on entend par bases de données vectorielles. Une base de données vectorielles doit permettre de stocker des vecteurs et rechercher des similarités de manière efficace et précise dans un espace vectoriel à haute dimension, en offrant une indexation performante et des opérations de calcul de distance adaptés selon le cas d’usage envisagé. Les cas d’usage de ces bases de données pouvant être les suivants:
Une base de données vectorielles doit également apporter les fonctionnalités attendues sur les bases de données relationnelles telles que les transactions, la sécurité, la scalabilité, la haute disponibilité et la recherche hybride. VecteursLes vecteurs produits par plongement vectorielle (embeddings) par les grands modèles de langage (LLM) sont des tableaux de données numériques (réels à virgule flottante, type real stocké sous 4 octects) permettant de représenter des données hétérogènes comme des images, des fichiers audios ou des textes. [-0.07, -0.53, -0.02, …, -0.61, 0.59]Les vecteurs sont de dimension finie dont le nombre varie selon les modèles ayant produits ces derniers. Par exemple, le modèle text-embedding-3-small de chez OpenAI produit des vecteurs de 1356 dimensions, alors que le modèle text-embedding-0004 de chez Google est à 768 dimensions. Chaque modèle définit également les types d’opérations de distance acceptées. pgvectorL’extension pgvector initié par Andrew Kane permet d’apporter à PostgreSQL le stockage et la recherche d’un nouveau type de données, le type vector à n dimensions. Il est possible d’utiliser la recherche exact et approximative (ANN). Par défaut, le type vector utilise le type real sous quatre octets pour le stockage, mais il est possible de réduire la taille de stockage en utilisant des vecteurs de demi précision, des binaires ou le type sparse. Pour comparer les vecteurs entre eux et faire des recherches de similarité, l’extension implémente plusieurs type d’opérations de distance en fonction de la nature des données et de l’objectif de la comparaison. On compte pas moins de six opérateurs de distance, les deux derniers opérateurs étant réservés au type vecteur binaire:
L’extension prend en charge également de nombreux langages existants pour les clients PostgreSQL. Pour démarrer, créons une table avec une colonne de type vecteur (à trois dimensions pour l’exemple), insérons des données et effectuons une recherche de similarité de documents selon la distance Euclidienne (ou L2) avec l’opérateur <-> : CREATE TABLE documents ( id serial PRIMARY KEY, embedding vector(3) ); INSERT INTO documents (embedding) VALUES ('[1,2,3]'), ('[4,5,6]'); SELECT * FROM documents ORDER BY embedding <-> '[3,1,2]' LIMIT 5;IndexationL’extension propose deux types de vecteurs pour la recherche aproximative (ANN) : IVFFlat et HNSW, en plus de la recherche exacte (recherche séquentielle). Le choix de l’un des types d’index est un compromis à faire entre performance et rappel. La performance étant entendue aussi bien en termes de construction de l’index que de recherche via cet index. Le rappel mesure quant à lui le ratio entre les éléments pertinents retournés parmi tous les éléments pertinents. Il est aussi possible de jouer avec les différents paramètres des index afin de placer le curseur selon votre cas d’usage. HNSWLe premier index disponible est l’index HNSW, pour Hierarchical Navigable Small World. Cet index est basé sur un graphe multi-couches, chaque couche étant plus ou moins dense. Plus on descend dans les couches, plus il y a de vecteurs. Pour effectuer une recherche ANN, il suffira de traverser le graphe à la recherche de la plus courte distance entre les vecteurs cibles.
La création de l’index HNSW peut se faire sans aucune données présentes initialement. Le temps de construction de l’index sera plus long et utilisera plus de mémoire que l’index IFVFlat, mais sera plus performant lors des requêtes. Il faudra créer un index par type d’opérateur de distance. L’index possède deux paramètres lors de la construction de ce dernier:
Par exemple: CREATE INDEX ON documents USING hnsw (embedding vector_cosine_ops) WITH (m = 16, ef_construction = 100);En augmentant ces paramètres, il est possible d’améliorer la valeur de rappel mais au détriment du temps de construction de l’index et de la mémoire utilisée. Il est aussi possible d’affiner la recherche avec le paramètre ef_search, mais au détriment de la vitesse de requête:
Il est possible également d’accélérer la création de l’index s’il peut contenir dans la taille définie par le paramètre maintenance_work_mem mais faire attention dans ce cas à ne pas consommer toute la mémoire disponible. On peut enfin rajouter des workers supplémentaires avec max_parallel_maintenance_workers et max_parallel_workers pour accélérer aussi la construction de l’index. IVFFlatLe deuxième index est l’index IVFFlat qui se base sur la création de liste (clusters) de vecteurs, et recherche un sous-ensemble de ces listes le plus proche du vecteur cible (avec l’algorithme K-means pour la recherche de centroïde). La construction de l’index ne peut se faire qu’après avoir inséré vos données. Cet index utilise moins de mémoire et est plus rapide à la construction que l’index HNSW mais est moins performant que ce dernier, en terme de vitesse et rappel.
Il est aussi important de noter que si la distribution des vecteurs change fréquemment, il sera nécessaire de reconstruire l’index (REINDEX CONCURRENTLY). L’index IVFFlat dispose d’un paramètre pour la construction:
Plus le nombre de liste est grand, plus la durée de construction sera longue. Pour la recherche, il est possible de modifier le paramètre:
En augmentant le paramètre probes, il est possible d’améliorer le rappel au détriment de la performance. On peut rajouter aussi des workers supplémentaires avec max_parallel_maintenance_workers et maw_parallel_workers pour accélérer aussi la construction de l’index comme avec l’index HNSW. Scan d’index itératifLa version 0.8.0 de pgvector a ajouté la possibilité d’activer le scan d’index itératif (désactivé par défaut). Avec cette fonctionnalité, PostgreSQL va scanner les index approximatifs à la recherche des plus proches voisins, appliquer ensuite les filtres additionnels (clause WHERE) puis scanner à nouveau les index si le nombre de voisins retournés n’est pas suffisant jusqu’à obtenir la valeur attendue. Il est possible de l’activer pour chaque index, et choisir l’ordre du tri par rapport à la distance entre éléments: SET hnsw.iterative_scan = strict_order|relaxed_order|off; SET ivfflat.iterative_scan = relaxed_order|off;Vous pouvez configurer le nombre d’éléments scannés pour chaque type d’index: SET hnsw.max_scan_tuples = 20000; (par défaut) SET ivfflat.max_probes = 100;QuantificationPar défaut, pgvector stocke le type vecteur sous 32 bits, en nombre à virgule flottante. Depuis la version 0.7.0, il est possible d’optimiser le stockage des vecteurs et la performance des requêtes en réduisant le nombre de bits utilisés pour stocker les vecteurs, et ainsi réduire la taille des index et donc l’empreinte mémoire et disque. On peut désormais utiliser le type halfvec stocké sous 16 bits et le type binaire bit. Par exemple: CREATE INDEX ON documents USING hnsw ((embedding::halfvec(1536)) halfvec_l2_ops); CREATE INDEX ON documents USING hnsw ((binary_quantize(embedding)::bit(3072)) bit_hamming_ops); SELECT id FROM documents ORDER BY binary_quantize(embedding)::bit(3072) <~> binary_quantize($1) LIMIT 10;Le type vecteur halfvec permet de stocker jusqu’à 4096 dimensions lorsque le type vecteur était limité à près de 2000 dimensions et le type binaire pouvant aller jusqu’à 64000 dimensions. L’inconvénient étant la réduction de l’information qui entraîne une diminution du rappel. ConclusionComme vous venez de le voir, PostgreSQL grâce à son extensibilité permet d’adresser différents cas d’usage, et dans cet article l’extension pgvector en est la parfaite illustration tranformant PostgreSQL en une base de données vectorielles tout en fournissant les fonctionnalités de la base de données relationnelles éprouvées depuis de nombreuses années. pgvector permet de répondre aux besoins issues autour de l’IA et sa popularité ne risque pas de retomber si l’on en croît le dépôt GitHub hébergeant le projet. RéférencesCrédits photos: Jerry Kavan |
|||||||
Loxodata
|
Recherche multilingue en texte intégral avec PostgreSQL (partie 2) |
|||||||
Bourgogne-Franche-Comté Publié le jeudi 16 janvier 2025 13h05 Importé le jeudi 16 janvier 2025 21h04 |
Utilisation en base de donnéesTests en base de donnéesCréation d’une table simple contenant des documents en plusieurs languesPour commencer, nous allons créer une table qui va contenir des documents collectés sur le net: CREATE TABLE pages (id BIGSERIAL PRIMARY KEY, url TEXT UNIQUE, lang CHAR(2) NOT NULL, title TEXT, content TEXT);La table contiendra simplement un indentifiant, l’url source du document, la langue du document, son titre et son contenu. Programme python d’alimentationPour nous constituer un jeu d’essai, nous allons simplement “scrapper” des pages du site Wikipedia en anglais et en français. Ce script va chercher dans notre table une URL pour lequel le document est absent, va lire l’URL en question, ajouter dans la table les autres URLs présentes dans le document, puis enregister le contenu du document sous forme de texte brut. Pour scrapper les sites respectivement en anglais et en français, le script se lance simplement: ~/loxodata_text$ python3 get_links.py en ~/loxodata_text$ python3 get_links.py frLe script: from bs4 import BeautifulSoup import requests import psycopg2 import sys def get_links(url,conn,cursor,lang): response = requests.get(url) data = response.text soup = BeautifulSoup(data, 'lxml') page1_html = BeautifulSoup(data, 'html.parser') page1_txt = page1_html.get_text() mots = page1_txt.split() # Supprimer espaces multiples for w in mots: if len(w) > 1024: mots.remove(w) # supprimer les chaines trop longues else: page1_txt = " ".join(mots) titre = soup.title.get_text() query = "UPDATE pages SET content=%s,title=%s WHERE url=%s;" cursor.execute(query,(page1_txt,titre,url)) for link in soup.find_all('a'): link_url = link.get('href') if link_url is not None and \ ('/Talk:' in link_url or \ '/wiki/Discussion' in link_url or \ '/wiki/CSS' in link_url or \ 'wiki/File:' in link_url or \ 'wiki/Fichier:' in link_url or \ '/User:' in link_url or \ '/User_talk:' in link_url): # éliminer les discussions/users, fichiers, ne garder que les articles link_url = None if link_url is not None and link_url.startswith('/wiki'): # traitement des URL relatives link_url='https://'+lang+'.wikipedia.org'+link_url if link_url is not None and link_url.startswith('https://'+lang+'.wikipedia.org/wiki'): query = "INSERT INTO pages (url,lang) VALUES (%s,%s) ON CONFLICT DO NOTHING;" data = (link_url) cursor.execute(query,(data,lang.upper())) conn.commit() return if __name__ == "__main__": if len(sys.argv) < 2: lang='en' else: lang=sys.argv[1] lang=lang.lower() r = 'https://'+lang+'.wikipedia.org/wiki/Main_Page' conn = psycopg2.connect(database='loxodata_text', host='localhost', user='aegir', port=5432) cursor = conn.cursor() # Ajouter l'URL de départ query = "INSERT INTO pages(url,lang) VALUES(%s,%s) ON CONFLICT DO NOTHING;" cursor.execute(query,(r,lang.upper())) conn.commit() stop = False documents=0 max_doc=10000 while not stop: query = "SELECT url FROM pages WHERE lang=%s AND content IS NULL LIMIT 1;" cursor.execute(query,(lang.upper(),)) r = cursor.fetchone() if r is None: stop = True else: documents=documents+1 print(documents,r[0]); get_links(r[0],conn,cursor,lang) if documents > max_doc: stop = TrueAprès avoir touné “un certain temps”, nous avons un jeu d’essai correct pour nos tests: loxodata_text=# select count(1) as urls, count(1) filter (where content is not null) as total, count(1) filter (where content is not null and lang='FR') as fr, count(1) filter (where content is not null and lang='EN') as en from pages; urls | total | fr | en ---------+-------+------+------ 1299347 | 14543 | 8393 | 6150 (1 row)Plus de 14.000 articles ont été chargés, dont 8.000 en français et 6.000 en anglais. Première recherche simpleDans cet exemple, je vais effectuer une recherche simple “thé & japonais”. Bien évidemment les résultats dépendent des pages qui auront été “scrappées” sur le wikipédia. La recherche s’effectue sur le contenu de la page. On affiche son titre et son URL. Mais surtout on utilise la fonction ts_rank() qui permet d’obtenir un score de correspondance. Zéro indiquant que le document ne correspond pas du tout, tandis que 1 indique que le document répond à 100%. Ceci permet de limiter la requête aux 10 documents les plus pertinents. loxodata_text=# select * from (select id,ts_rank(to_tsvector('french_custom',content),to_tsquery('french_custom','thé & japonais') ) , title,url from pages where lang='FR' and to_tsquery('french_custom','thé & japonais') @@ to_tsvector('french',content) order by 2 desc) foo limit 10 ; id | ts_rank | title | url -------+------------+----------------------------------------+------------------------------------------------------------------------- 1716 | 0.99486476 | Thé au Japon — Wikipédia | https://fr.wikipedia.org/wiki/Th%C3%A9_au_Japon 13527 | 0.9795128 | Thé vert — Wikipédia | https://fr.wikipedia.org/wiki/Th%C3%A9_vert 13056 | 0.8625401 | Cérémonie du thé japonaise — Wikipédia | https://fr.wikipedia.org/wiki/C%C3%A9r%C3%A9monie_du_th%C3%A9_japonaise 25315 | 0.8625401 | Cérémonie du thé japonaise — Wikipédia | https://fr.wikipedia.org/wiki/Chad%C3%B4 22413 | 0.8625401 | Cérémonie du thé japonaise — Wikipédia | https://fr.wikipedia.org/wiki/Chanoyu 13023 | 0.81228346 | Thé — Wikipédia | https://fr.wikipedia.org/wiki/Th%C3%A9 13979 | 0.7667292 | Catégorie:Thé au Japon — Wikipédia | https://fr.wikipedia.org/wiki/Cat%C3%A9gorie:Th%C3%A9_au_Japon 1745 | 0.73748296 | Bancha (thé) — Wikipédia | https://fr.wikipedia.org/wiki/Bancha_(th%C3%A9) 1730 | 0.7290929 | Cérémonie du thé — Wikipédia | https://fr.wikipedia.org/wiki/C%C3%A9r%C3%A9monie_du_th%C3%A9 1736 | 0.71149355 | Sencha — Wikipédia | https://fr.wikipedia.org/wiki/Sencha (10 rows)Notre recherche ne s’effectuant que sur le contenu de la page, il pourrait être pertinent d’ajouter le titre de la page au texte dans lequel on fait une recherche, au moins pour calculer le score: loxodata_text=# select * from (select id,ts_rank(to_tsvector('french_custom',title || ' ' || content),to_tsquery('french_custom','thé & japonais') ) , title,url from pages where lang='FR' and to_tsquery('french_custom','thé & japonais') @@ to_tsvector('french',content) order by 2 desc) foo limit 10 ; id | ts_rank | title | url -------+------------+----------------------------------------+------------------------------------------------------------------------- 1716 | 0.9961827 | Thé au Japon — Wikipédia | https://fr.wikipedia.org/wiki/Th%C3%A9_au_Japon 13527 | 0.9795128 | Thé vert — Wikipédia | https://fr.wikipedia.org/wiki/Th%C3%A9_vert 13056 | 0.8625401 | Cérémonie du thé japonaise — Wikipédia | https://fr.wikipedia.org/wiki/C%C3%A9r%C3%A9monie_du_th%C3%A9_japonaise 25315 | 0.8625401 | Cérémonie du thé japonaise — Wikipédia | https://fr.wikipedia.org/wiki/Chad%C3%B4 22413 | 0.8625401 | Cérémonie du thé japonaise — Wikipédia | https://fr.wikipedia.org/wiki/Chanoyu 13979 | 0.8246348 | Catégorie:Thé au Japon — Wikipédia | https://fr.wikipedia.org/wiki/Cat%C3%A9gorie:Th%C3%A9_au_Japon 13023 | 0.81228346 | Thé — Wikipédia | https://fr.wikipedia.org/wiki/Th%C3%A9 1745 | 0.73748296 | Bancha (thé) — Wikipédia | https://fr.wikipedia.org/wiki/Bancha_(th%C3%A9) 1730 | 0.7290929 | Cérémonie du thé — Wikipédia | https://fr.wikipedia.org/wiki/C%C3%A9r%C3%A9monie_du_th%C3%A9 1736 | 0.71149355 | Sencha — Wikipédia | https://fr.wikipedia.org/wiki/Sencha (10 rows)On peut voir ainsi que le score de la page intitulée “Catégorie:Thé au Japon” a été légèrement amélioré, ce qui permet à ce document d’être classé avant la page générale “Thé”. Le poids des mots… sans photoPostgreSQL permet de donner plus d’importance (plus de poids) aux mots d’une certaine partie d’un document. Cela s’effectue avec la fonction setweight(ts_vector,poids). Le poids est une simple lettre A,B,C ou D (par ordre décroissant). Ce poids figure dans les éléments d’un ts_vector. Pour rappel, voici un ts_vector sans poids: loxodata_text=# select to_tsvector('french_custom','Vive postgres'); to_tsvector -------------------- 'postgr':2 'viv':1 (1 row)Voici ce même vecteur auquel on a attribué le poids ‘A’ : loxodata_text=# select setweight(to_tsvector('french_custom','Vive postgres'),'A'); setweight ---------------------- 'postgr':2A 'viv':1A (1 row)Et voici maintenaant la concaténation de deux vecteurs de poids différents: loxodata_text=# select setweight(to_tsvector('french_custom','Vive postgres'),'A') || setweight(to_tsvector('french_custom','PostgreSQL est un SGBDR'),'B'); ?column? ------------------------------------ 'postgr':2A,3B 'sgbdr':6B 'viv':1A (1 row)On peut donc effectuer notre test précédent en attribuant un poids supérieur au titre du document (on affiche cette fois 12 résultats au lieu de 10) : loxodata_text=# select * from (select id,ts_rank(setweight(to_tsvector('french_custom',title),'A') || setweight(to_tsvector('french_custom',content),'B'), to_tsquery('french_custom','thé & japonais')) , title,url from pages where lang='FR' and to_tsquery('french_custom','thé & japonais') @@ to_tsvector('french',content) order by 2 desc) foo limit 12 ; id | ts_rank | title | url -------+------------+----------------------------------------+------------------------------------------------------------------------- 1716 | 0.99999994 | Thé au Japon — Wikipédia | https://fr.wikipedia.org/wiki/Th%C3%A9_au_Japon 13527 | 0.99999994 | Thé vert — Wikipédia | https://fr.wikipedia.org/wiki/Th%C3%A9_vert 13979 | 0.99999684 | Catégorie:Thé au Japon — Wikipédia | https://fr.wikipedia.org/wiki/Cat%C3%A9gorie:Th%C3%A9_au_Japon 22800 | 0.9999663 | Catégorie:Thé japonais — Wikipédia | https://fr.wikipedia.org/wiki/Cat%C3%A9gorie:Th%C3%A9_japonais 13056 | 0.99990284 | Cérémonie du thé japonaise — Wikipédia | https://fr.wikipedia.org/wiki/C%C3%A9r%C3%A9monie_du_th%C3%A9_japonaise 25315 | 0.99990284 | Cérémonie du thé japonaise — Wikipédia | https://fr.wikipedia.org/wiki/Chad%C3%B4 22413 | 0.99990284 | Cérémonie du thé japonaise — Wikipédia | https://fr.wikipedia.org/wiki/Chanoyu 13023 | 0.99958086 | Thé — Wikipédia | https://fr.wikipedia.org/wiki/Th%C3%A9 1745 | 0.9980019 | Bancha (thé) — Wikipédia | https://fr.wikipedia.org/wiki/Bancha_(th%C3%A9) 1730 | 0.9977101 | Cérémonie du thé — Wikipédia | https://fr.wikipedia.org/wiki/C%C3%A9r%C3%A9monie_du_th%C3%A9 1736 | 0.9971023 | Sencha — Wikipédia | https://fr.wikipedia.org/wiki/Sencha 13321 | 0.99643356 | Kamairicha — Wikipédia | https://fr.wikipedia.org/wiki/Kamairicha (12 rows)Cela à permis de faire apparaître “Catégorie:Thé japonais” en quatrième position, tandis que l’article sur le Sencha est passé à la onzième place. Extrait pertinentPlutôt qu’afficher l’URL, il peut être intéressant d’afficher l’extraît de texte le plus pertinent du document. Cela peut se faire avec la fonction ts_headline que nous pouvons appliquer aux 5 premiers résultats de notre requête: loxodata_text=# select id,rank,title, ts_headline('french_custom',title||' '||content,to_tsquery('french_custom','thé & japonais')) from (select id,ts_rank(setweight(to_tsvector('french_custom',title),'A') || setweight(to_tsvector('french_custom',content),'B'), to_tsquery('french_custom','thé & japonais')) as rank , title,url,content from pages where lang='FR' and to_tsquery('french_custom','thé & japonais') @@ to_tsvector('french',content) order by 2 desc) foo limit 5 ; id | rank | title | ts_headline -------+------------+----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------- 13527 | 0.99999994 | Thé vert — Wikipédia | <b>Thé</b> au <b>Japon</b>. <b>Thé</b> vert <b>japonais</b> Sencha <b>Thé</b> vert Genmaicha Le <b>Japon</b> produit essentiellement du <b>thé</b> 1716 | 0.99999994 | Thé au Japon — Wikipédia | <b>thé</b> au <b>Japon</b>. Le <b>thé</b> de Toganoo est considéré comme le meilleur <b>thé</b> du <b>Japon</b> 13979 | 0.99999684 | Catégorie:Thé au Japon — Wikipédia | <b>Thé</b> <b>japonais</b> – 20 PM Maître de <b>thé</b> <b>japonais</b> – 27 P Pages dans la catégorie « <b>Thé</b> 22800 | 0.9999663 | Catégorie:Thé japonais — Wikipédia | <b>Thé</b> <b>japonais</b> — Wikipédia Catégorie:<b>Thé</b> <b>japonais</b> — Wikipédia Aller au contenu Menu principal Menu principal déplacer 13056 | 0.99990284 | Cérémonie du thé japonaise — Wikipédia | <b>thé</b> au <b>Japon</b>, ou « service <b>japonais</b> du <b>thé</b> », appelée chanoyu, ou sadō, ou encore (5 rows)La taille du ou des extraits retournés est un paramètre de la fonction ts_headline() de même que les balises de mise en évidence (<b></b>). Attention, cette fonction est coûteuse en CPU, c’est pourquoi il est convenable d’être attentif à ne l’appliquer que sur un resultset déjà réduit au maximum. PerformancesSi vous avez essayé, de votre côté, de reproduire les exemples précédents au fur et à mesure de votre lecture, il est probable que vous éprouviez quelques inquiétudes quant aux performances du FTS. Le problème étant que la fonction to_tsvector() est “lente”. Si l’on souhaite effectuer des recherches avec des performances correctes, il est impératif de précalculer ces vecteurs de lexèmes. On va donc ajouter une colonne de type tsvector à notre table: loxodata_text=# alter table pages add column vector tsvector; ALTER TABLEPuis nous allons précalculer nos vecteurs conformément à la langue du document. Dans le cas d’une base de données en exploitation, il serait bien sûr beaucoup plus pertinent de mettre un trigger sur la table afin que le champ vector soit renseigné/mis à jour lors des INSERT ou UPDATE: loxodata_text=# update pages set vector = to_tsvector('french_custom',title || ' ' || content) where lang = 'FR' and content is not null; UPDATE 8393 Time: 1371518,736 ms (22:51,519) loxodata_text=# update pages set vector = to_tsvector('english_custom',title || ' ' || content) where lang = 'EN' and content is not null; UPDATE 6150 Time: 351283,849 ms (05:51,284)Si nous effectuons notre recherche originale sur le thé japonais avec un EXPLAIN ANALYZE successivement en calculant le vecteur puis en utilisant le champ vector qui vient d’être créé nous avons les résultats suivants: loxodata_text=# explain analyze select id, title,url from pages where lang='FR' and to_tsquery('french_custom','thé & japonais') @@ to_tsvector('french_custom',content); QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------- Gather (cost=1000.00..169567.06 rows=15 width=99) (actual time=373.272..21921.275 rows=3007 loops=1) Workers Planned: 2 Workers Launched: 2 -> Parallel Seq Scan on pages (cost=0.00..168565.56 rows=6 width=99) (actual time=322.930..21800.415 rows=1002 loops=3) Filter: ((lang = 'FR'::bpchar) AND ('''the'' & ''japon'''::tsquery @@ to_tsvector('french_custom'::regconfig, content))) Rows Removed by Filter: 432113 Planning Time: 0.138 ms Execution Time: 21921.710 ms (8 rows) Time: 21922,225 ms (00:21,922) loxodata_text=# explain analyze select id, title,url from pages where lang='FR' and to_tsquery('french_custom','thé & japonais') @@ vector; QUERY PLAN -------------------------------------------------------------------------------------------------------------------------- Gather (cost=1000.00..34297.92 rows=810 width=99) (actual time=0.414..479.358 rows=3007 loops=1) Workers Planned: 2 Workers Launched: 2 -> Parallel Seq Scan on pages (cost=0.00..33216.92 rows=338 width=99) (actual time=0.218..384.590 rows=1002 loops=3) Filter: (('''the'' & ''japon'''::tsquery @@ vector) AND (lang = 'FR'::bpchar)) Rows Removed by Filter: 432113 Planning Time: 0.158 ms Execution Time: 479.523 ms (8 rows) Time: 480,046 msPour le moment, laissons de côté le temps d’éxécution qui est beaucoup lié à l’état des caches. On peut voir que le coût estimé par le planner est déjà divisé par 5 (34297.92 vs 169567.06) en utilisant notre champ précalculé. On aurait pu être tenté de partitionner notre table pages sur la langue, mais l’intérêt serait limité puisqu’on peut également créer des index partiels. Pour rappel, si un tableau est indexé dans un index BTree, l’index permettra de trouver rapidement exactement ce tableau dans son intégralité. Tandis que des index GiN ou GiST permettront de retrouver les tableaux qui contiennent les éléments recherchés. Nous allons donc indexer les éléments du champ vector pour chaque langue: loxodata_text=# create index x_pages_vector_fr ON pages USING GIN(vector) where lang='FR'; CREATE INDEX Time: 10520,209 ms (00:10,520) loxodata_text=# create index x_pages_vector_en ON pages USING GIN(vector) where lang='EN'; CREATE INDEX Time: 11435,435 ms (00:11,435)Le EXPLAIN ANALYZE de la requête de recherche devient ainsi: loxodata_text=# explain analyze select id, title,url from pages where lang='FR' and to_tsquery('french_custom','thé & japonais') @@ vector; QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------- Bitmap Heap Scan on pages (cost=40.69..2817.94 rows=810 width=99) (actual time=0.446..2.632 rows=3007 loops=1) Recheck Cond: (('''the'' & ''japon'''::tsquery @@ vector) AND (lang = 'FR'::bpchar)) Heap Blocks: exact=606 -> Bitmap Index Scan on x_pages_vector_fr (cost=0.00..40.48 rows=810 width=0) (actual time=0.392..0.392 rows=3007 loops=1) Index Cond: (vector @@ '''the'' & ''japon'''::tsquery) Planning Time: 0.347 ms Execution Time: 2.731 ms (7 rows) Time: 3,329 msComme on peut le voir, cet index permet de diviser par douze le coût estimé par le planner. Le cas de l’index GiSTSi on compare l’exécution avec un index GiST au lieu de GIN nous avons: loxodata_text=# drop index x_pages_vector_fr; DROP INDEX Time: 155,098 ms loxodata_text=# drop index x_pages_vector_en; DROP INDEX Time: 45,920 ms loxodata_text=# CREATE INDEX x_pages_vector_fr ON pages USING GIST(vector tsvector_ops) WHERE lang='FR'; CREATE INDEX Time: 1969,569 ms (00:01,970) loxodata_text=# CREATE INDEX x_pages_vector_en ON pages USING GIST(vector tsvector_ops) WHERE lang='EN'; CREATE INDEX Time: 1891,561 ms (00:01,892) loxodata_text=# explain analyze select id, title,url from pages where lang='FR' and to_tsquery('french_custom','thé & japonais') @@ vector; QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------- Bitmap Heap Scan on pages (cost=36.59..3608.35 rows=1072 width=99) (actual time=1.882..69.167 rows=3007 loops=1) Recheck Cond: (('''the'' & ''japon'''::tsquery @@ vector) AND (lang = 'FR'::bpchar)) Rows Removed by Index Recheck: 1533 Heap Blocks: exact=750 -> Bitmap Index Scan on x_pages_vector_fr (cost=0.00..36.32 rows=1072 width=0) (actual time=1.724..1.725 rows=4540 loops=1) Index Cond: (vector @@ '''the'' & ''japon'''::tsquery) Planning Time: 0.199 ms Execution Time: 69.357 ms (8 rows)On peut voir que le coût estimé est supérieur avec un GiST qu’avec un GIN. Le point le plus intéressant c’est que le scan de l’index GiST a ramené plus de lignes (4540) que celui de l’index GIN lequel a ramené exactement le même nombre de lignes (3007) que la requête elle-même. Ce comportement était prévisible car si le GIN indexe des valeurs exactes, le GiST indexe lui des checksums de valeurs, ce qui entraîne de faux positifs et donc nécessite un filtrage après coup des lignes ramenées par le scan de l’index, et donc des lectures superflues, et donc forcément un coût supplémentaire. L’utilisation d’un index GiST peut cependant parfois se justifier, en particulier parce qu’il supporte l’inclusion de valeurs (CREATE INDEX ... INCLUDE (champ)). Donc si votre table de documents comporte d’autres champs quasi-systématiquement utilisés dans la clause WHERE (identifiant de l’auteur, droits d’accès etc.) l’utilisation du GiST peut être pertinente afin de pouvoir inclure cette ou ces donnée(s) à l’index. LimitesIl faut savoir que lorsque des ts_vector sont indexés, seuls les lexèmes le sont. Le poids éventuellement associé à chaque lexème ne l’est pas. Cela ne pose en soit pas de problème, mais si vous avez précalculé votre champ vector en concaténant des fragments de texte de poids différents, ne soyez pas surpris d’avoir éventuellement 2 champs vector différents qui, selon l’index sont égaux. ConclusionLes capacités de recherches en texte intégral de PostgreSQL sont très largement méconnues, surtout en France, alors que quelques simples efforts de configurations permettraient dans bien des cas d’espèce de s’affranchir de coûteux moteurs spécialisés et propriétaires. ConfigurationSi la configuration par défaut de la recherche en texte intégral de PostgreSQL est assez efficace en anglais, il convient pour le français (ou l’espagnol) de compléter le paramétrage par défaut. Pour cela:
Modélisation
Maintenance
VolumétriesPour rappel, j’ai constitué pour rédiger cet article une base contenant 14.543 articles de wikipédia. Cela représente 493 Mo de texte brut: loxodata_text=# select pg_size_pretty(sum(octet_length(content))) from pages; pg_size_pretty ---------------- 493 MBGrace au mécanisme de compression intégré à pg_toast, ces textes n’occupent que 264 Mo dans la base: loxodata_text=# select pg_size_pretty(sum(pg_column_size(content))) from pages; pg_size_pretty ---------------- 264 MBNotez que j’ai utilisé la compression transparente par défaut pour les champs TOASTed PGLZ (champs TEXT et TS_VECTOR). Depuis la version 14 de PostgreSQL, la compression LZ4 est disponible, paramétrable champ par champ si besoin, laquelle permet une amélioration significative des performances au détriment d’une perte de compression infinitésimale. N’oubliez pas d’explorer ce point dans votre tuning. Le champ ts_vector précalculé occupe 294 Mo: loxodata_text=# select pg_size_pretty(sum(pg_column_size(vector))) from pages; pg_size_pretty ---------------- 294 MBLes index GIN occupent 122 Mo: loxodata_text=# select pg_size_pretty(pg_relation_size('x_pages_vector_en') + pg_relation_size('x_pages_vector_fr') ); pg_size_pretty ---------------- 122 MBIl semble donc raisonnable de prévoir au moins 1,4 Mo d’espace de stockage pour chaque Mo de texte brut dans le cadre d’une base conçue pour la recherche en texte intégral. |
|||||||
Loxodata
|
Recherche multilingue en texte intégral avec PostgreSQL (partie 1) |
|||||||
Bourgogne-Franche-Comté Publié le jeudi 16 janvier 2025 13h00 Importé le jeudi 16 janvier 2025 21h04 |
Principes et configurationsHistoriqueEn 2000, des développements pour PostgreSQL basés sur OpenFTS ont débuté. Ce projet était alors nommé Tsearch. En 2003 le projet est devenu Tsearch2, utilisant le nouveau type de données tsvector et les index GiN/GiST de PostgreSQL 8.2 ainsi que l’UTF8. La recherche en texte intégral (ou FTS pour Full-Text Search) était proposée dans une contribution séparée nommée tsearch2 et développée par Oleg Bartunov et Teodor Sigaev. La contribution a été pleinement intégrée dans PostgreSQL à partir de la version 8.3. L’objet de ce document est donc de présenter la recherche en plein texte disponible avec la distribution standard de PostgreSQL. Principe généralDécomposition des documentsLa recherche en texte intégral diffère de la simple recherche basée sur les chaînes de caractères. Il s’agit en effet d’effectuer une recherche sémantique et non pas une simple recherche d’expression régulière. PostgreSQL est doté d’outils puissants permettant de travailler sur les chaînes de caractères, évaluer la similarité entre deux chaînes, etc. On peut citer par exemple l’extension pg_trgm (trigrammes) particulièrement utile pour de telles recherches. On peut résumer la recherche sémantique en quelques étapes simples (on nomme “document” le texte qui fera ultérieurement l’objet d’une recherche) :
Voici un exemple simple de transformation d’un texte en vecteur de lexèmes en guise d’illustration: loxodata_text=# select to_tsvector('english','I love postgres, but she loves shopping with a $100 banknote'); to_tsvector ------------------------------------------------------ '100':10 'banknot':11 'love':2,6 'postgr':3 'shop':7 (1 row)On peut voir que le texte a été décomposé en 5 lexèmes, et que le lexème “love” est présent sur deux positions: 2 et 6. La fonction ts_debug() permet d’avoir plus de détails sur cette transformation: loxodata_text=# select * from ts_debug('english', 'I love postgres, but she loves shopping with a $100 banknote'); alias | description | token | dictionaries | dictionary | lexemes -----------+------------------+----------+----------------+--------------+----------- asciiword | Word, all ASCII | I | {english_stem} | english_stem | {} blank | Space symbols | | {} | | asciiword | Word, all ASCII | love | {english_stem} | english_stem | {love} blank | Space symbols | | {} | | asciiword | Word, all ASCII | postgres | {english_stem} | english_stem | {postgr} blank | Space symbols | , | {} | | asciiword | Word, all ASCII | but | {english_stem} | english_stem | {} blank | Space symbols | | {} | | asciiword | Word, all ASCII | she | {english_stem} | english_stem | {} blank | Space symbols | | {} | | asciiword | Word, all ASCII | loves | {english_stem} | english_stem | {love} blank | Space symbols | | {} | | asciiword | Word, all ASCII | shopping | {english_stem} | english_stem | {shop} blank | Space symbols | | {} | | asciiword | Word, all ASCII | with | {english_stem} | english_stem | {} blank | Space symbols | | {} | | asciiword | Word, all ASCII | a | {english_stem} | english_stem | {} blank | Space symbols | $ | {} | | uint | Unsigned integer | 100 | {simple} | simple | {100} blank | Space symbols | | {} | | asciiword | Word, all ASCII | banknote | {english_stem} | english_stem | {banknot} (21 rows)La sortie de ts_debug() indique que les caractères virgule et dollar (",$") ont été considérés comme des espaces, «100» est bien détecté comme un entier non signé, et les mots «I,but,she,with,a» n’ont pas été convertis en lexèmes. Ces derniers sont en effet des «stop words», c’est-à-dire des mots trop courants pour être significatifs, ils sont donc éliminés du vecteur de lexèmes. Requête de rechercheLa requête de recherche va suivre le même principe: les éléments recherchés vont être décomposés en lexèmes, et PostgreSQL va chercher des éléments communs entre les deux vecteurs. loxodata_text=# select to_tsquery('english','shops & banknotes'); to_tsquery -------------------- 'shop' & 'banknot' (1 row)Comme vous l’aurez deviné, le & est un opérateur logique signifiant ET. Les différents opérateurs logiques pour une requête en plein texte sont:
Et enfin, l’opérateur @@ teste la correspondance entre un vecteur et une requête. On peut ainsi tester, par exemple, une requête shops & (banknotes | credit <-> card), c’est à dire «contient ‘shop’ ET (soit (‘banknotes’) soit (‘credit’ suivi de ‘card’)) » avec différentes phrases: loxodata_text=# WITH docs as (SELECT unnest(ARRAY['I love postgres, but she loves shopping with a $100 banknote','I love postgres, but she loves shopping with a credit card', 'I love postgres, but she loves shopping with a card for credit', 'I love $100 banknotes']) as sentence) SELECT to_tsquery('english','shops & (banknotes | credit <-> card)') @@ to_tsvector('english',sentence) result, sentence FROM docs; result | sentence --------+---------------------------------------------------------------- t | I love postgres, but she loves shopping with a $100 banknote t | I love postgres, but she loves shopping with a credit card f | I love postgres, but she loves shopping with a card for credit f | I love $100 banknotes (4 rows)La requête retourne False pour la troisième phrase car le mot ‘card’ ne suit pas immédiatement ‘credit’, et la quatrième phrase retourne également False du fait de l’absence du lexème ‘shop’. Il faut noter que les positions enregistrées dans le vecteur tiennent compte de la présence de stop words. Ainsi ‘credit for card’ ne correspondra pas à ‘credit <-> card’ bien que ‘for’ soit un stop word. ConfigurationsTout d’abord une précision: les configurations FTS se font base par base, elles ne sont pas globales au cluster (i.e. instance). Différentes languesDans ces premiers exemples, nous avons utilisé uniquement l’anglais pour une raison très simple: PostgreSQL est livré bien configuré pour l’anglais. Cependant pour le français, même si le support est présent, quelques ajustements sont nécessaires. Commençons par faire une copie de la configuration par défaut: loxodata_text=# CREATE TEXT SEARCH CONFIGURATION french_custom ( COPY=french ); CREATE TEXT SEARCH CONFIGURATIONNous pouvons examiner les différents éléments lexicographiques définis dans cette configuration: loxodata_text=# \dF+ french_custom Text search configuration "public.french_custom" Parser: "pg_catalog.default" Token | Dictionaries -----------------+-------------- asciihword | french_stem asciiword | french_stem email | simple file | simple float | simple host | simple hword | french_stem hword_asciipart | french_stem hword_numpart | simple hword_part | french_stem int | simple numhword | simple numword | simple sfloat | simple uint | simple url | simple url_path | simple version | simple word | french_stemUn premier test rapide nous montre une difficulté liée à la langue française: les accents. loxodata_text=# select title,to_tsvector('french',title) from pages where id=186; title | to_tsvector -----------------------+---------------------------- Imprimeur — Wikipédia | 'imprimeur':1 'wikipédi':2 (1 row)Cela poserait un problème, par exemple, avec les participes passés, puisque “mange” et “mangé” seraient des lexèmes différents. On peut donc utiliser l’extension standard UNACCENT et l’ajouter à notre configuration: loxodata_text=# CREATE EXTENSION IF NOT EXISTS unaccent; NOTICE: extension "unaccent" already exists, skipping CREATE EXTENSION loxodata_text=# ALTER TEXT SEARCH CONFIGURATION french_custom ALTER MAPPING FOR hword, hword_part, word WITH unaccent, french_stem; ALTER TEXT SEARCH CONFIGURATIONVérifions la prise en compte de unaccent sur notre configuration: loxodata_text=# \dF+ french_custom Text search configuration "public.french_custom" Parser: "pg_catalog.default" Token | Dictionaries -----------------+---------------------- asciihword | french_stem asciiword | french_stem email | simple file | simple float | simple host | simple hword | unaccent,french_stem hword_asciipart | french_stem hword_numpart | simple hword_part | unaccent,french_stem int | simple numhword | simple numword | simple sfloat | simple uint | simple url | simple url_path | simple version | simple word | unaccent,french_stemNous pouvons faire un test rapide avec ts_debug() pour voir le comportement: loxodata_text=# select ts_debug('french_custom','Cet article est écrit en 2024 pour être publié sur le blog de Loxodata (https://www.loxodata.fr/post/)'); ts_debug ------------------------------------------------------------------------------- (asciiword,"Word, all ASCII",Cet,{french_stem},french_stem,{cet}) (blank,"Space symbols"," ",{},,) (asciiword,"Word, all ASCII",article,{french_stem},french_stem,{articl}) (blank,"Space symbols"," ",{},,) (asciiword,"Word, all ASCII",est,{french_stem},french_stem,{}) (blank,"Space symbols"," ",{},,) (word,"Word, all letters",écrit,"{unaccent,french_stem}",unaccent,{ecrit}) (blank,"Space symbols"," ",{},,) (asciiword,"Word, all ASCII",en,{french_stem},french_stem,{}) (blank,"Space symbols"," ",{},,) (uint,"Unsigned integer",2024,{simple},simple,{2024}) (blank,"Space symbols"," ",{},,) (asciiword,"Word, all ASCII",pour,{french_stem},french_stem,{}) (blank,"Space symbols"," ",{},,) (word,"Word, all letters",être,"{unaccent,french_stem}",unaccent,{etre}) (blank,"Space symbols"," ",{},,) (word,"Word, all letters",publié,"{unaccent,french_stem}",unaccent,{publie}) (blank,"Space symbols"," ",{},,) (asciiword,"Word, all ASCII",sur,{french_stem},french_stem,{}) (blank,"Space symbols"," ",{},,) (asciiword,"Word, all ASCII",le,{french_stem},french_stem,{}) (blank,"Space symbols"," ",{},,) (asciiword,"Word, all ASCII",blog,{french_stem},french_stem,{blog}) (blank,"Space symbols"," ",{},,) (asciiword,"Word, all ASCII",de,{french_stem},french_stem,{}) (blank,"Space symbols"," ",{},,) (asciiword,"Word, all ASCII",Loxodata,{french_stem},french_stem,{loxodat}) (blank,"Space symbols"," (",{},,) (protocol,"Protocol head",https://,{},,) (url,URL,"www.loxodata.fr/post/)",{simple},simple,"{www.loxodata.fr/post/)}") (host,Host,www.loxodata.fr,{simple},simple,{www.loxodata.fr}) (url_path,"URL path","/post/)",{simple},simple,"{/post/)}") (32 rows)Sur les 32 éléments lexicographiques, 6 ont été éliminés (est, en, pour…) car figurant dans les “stop words”. La plupart des éléments sont des “mots”, nous avons également un nombre entier (2024) et une URL. Les accents ont bien été supprimés des lexèmes (“etre”, “publie”…) Choix des éléments lexicographiques à traiterSelon les types de documents que nous souhaitons traiter, nous pouvons éliminer des éléments à traiter. Ainsi nous pouvons éliminer les valeurs numériques, les URLs et les adresses emails de nos configurations français et anglais: loxodata_text=# ALTER TEXT SEARCH CONFIGURATION french_custom DROP MAPPING FOR email, sfloat, float, int, uint, url, host, url_path; ALTER TEXT SEARCH CONFIGURATION loxodata_text=# ALTER TEXT SEARCH CONFIGURATION english_custom DROP MAPPING FOR email, sfloat, float, int, uint, url, host, url_path; ALTER TEXT SEARCH CONFIGURATION loxodata_text=#Un nouveau test avec ts_debug() montre que ces éléments lexicographiques (nombre et url) sont désormais ignorés lors de l’utilisation de la configuration french_custom: loxodata_text=# select ts_debug('french_custom','Cet article est écrit en 2024 pour être publié sur le blog de Loxodata (https://www.loxodata.fr/post/)'); ts_debug ------------------------------------------------------------------------------ (asciiword,"Word, all ASCII",Cet,{french_stem},french_stem,{cet}) (blank,"Space symbols"," ",{},,) (asciiword,"Word, all ASCII",article,{french_stem},french_stem,{articl}) (blank,"Space symbols"," ",{},,) (asciiword,"Word, all ASCII",est,{french_stem},french_stem,{}) (blank,"Space symbols"," ",{},,) (word,"Word, all letters",écrit,"{unaccent,french_stem}",unaccent,{ecrit}) (blank,"Space symbols"," ",{},,) (asciiword,"Word, all ASCII",en,{french_stem},french_stem,{}) (blank,"Space symbols"," ",{},,) (uint,"Unsigned integer",2024,{},,) (blank,"Space symbols"," ",{},,) (asciiword,"Word, all ASCII",pour,{french_stem},french_stem,{}) (blank,"Space symbols"," ",{},,) (word,"Word, all letters",être,"{unaccent,french_stem}",unaccent,{etre}) (blank,"Space symbols"," ",{},,) (word,"Word, all letters",publié,"{unaccent,french_stem}",unaccent,{publie}) (blank,"Space symbols"," ",{},,) (asciiword,"Word, all ASCII",sur,{french_stem},french_stem,{}) (blank,"Space symbols"," ",{},,) (asciiword,"Word, all ASCII",le,{french_stem},french_stem,{}) (blank,"Space symbols"," ",{},,) (asciiword,"Word, all ASCII",blog,{french_stem},french_stem,{blog}) (blank,"Space symbols"," ",{},,) (asciiword,"Word, all ASCII",de,{french_stem},french_stem,{}) (blank,"Space symbols"," ",{},,) (asciiword,"Word, all ASCII",Loxodata,{french_stem},french_stem,{loxodat}) (blank,"Space symbols"," (",{},,) (protocol,"Protocol head",https://,{},,) (url,URL,"www.loxodata.fr/post/)",{},,) (host,Host,www.loxodata.fr,{},,) (url_path,"URL path","/post/)",{},,) (32 rows)Stop-wordsOn peut constater que le fichier des stop-words français fourni par défaut est très succinct: loxodata_text=# select to_tsvector('french_custom','le la les ce ça'); to_tsvector --------------- 'ca':5 'le':3 (1 row)“ça” et “les” n’y figurent pas par exemple. Mais nous pouvons télécharger un fichier plus complet et le placer dans la configuration tsearch (le fichier doit obligatoirement avoir le suffixe .stop) : ~/loxodata_text$ wget https://raw.githubusercontent.com/stopwords-iso/stopwords-fr/refs/heads/master/stopwords-fr.txt ~/loxodata_text$ sudo cp stopwords-fr.txt /opt/pgsql/16/share/tsearch_data/french_custom.stopPuis modifier la configuration du dictionnaire français pour utiliser ce nouveau fichier: loxodata_text=# alter TEXT SEARCH DICTIONARY french_stem(STOPWORDS = french_custom ); ALTER TEXT SEARCH DICTIONARYEt maintenant, vérifions la prise en compte de cette nouvelle configuration: loxodata_text=# select to_tsvector('french_custom','le la les ce ça'); to_tsvector ------------- 'ca':5 (1 row)Si “les” est bien maintenant considéré comme un stop-word, il n’en est pas de même pour “ça” ce qui peut surprendre, car ce mot figure bien dans notre fichier: ~/loxodata_text$ grep -n "ça" stopwords-fr.txt 676:çaL’explication est simple, les stop-words sont appliqués après le filtre “unaccent”. Il convient donc de modifier ce fichier afin d’en retirer également les accents. Le fichier de stop-words étant un simple fichier texte, il est aisé de le modifier: ~/loxodata_text$ sudo bash -c "sed -i -e 's/ç/c/g' /opt/pgsql/16/share/tsearch_data/french_custom.stop"Ensuite, il faut refaire notre ALTER TEXT SEARCH DICTIONARY afin de recharger le fichier de stop-words: loxodata_text=# alter TEXT SEARCH DICTIONARY french_stem(STOPWORDS = french_custom ); ALTER TEXT SEARCH DICTIONARY loxodata_text=# select to_tsvector('french_custom','le la les ce ça'); to_tsvector ------------- (1 row)“ça” est donc bien maintenant un stop-word. Il faudrait bien évidemment effectuer la substitution pour chaque type de caractère accentué ( ’s/é/e/g' etc. ) la commande tr ne pouvant être utilisée car elle n’est pas compatible avec l’UTF8. SynonymesIl peut être utile dans le cadre de la recherche en texte intégral de disposer d’un dictionnaire de synonymes. Là encore, c’est une configuration spécifique à chaque langue qui doit être effectuée. Bien évidemment le dictionnaire à utiliser dépendra beaucoup de la nature des documents à indexer (documentation technique, juridique, etc.). Comme pour les stop-words, il faut placer un fichier de synonymes dans le répertoire de configuration tsearch_data. Ce dictionnaire doit obligatoirement avoir le suffixe .syn. J’ai donc ainsi créé un fichier french_custom.syn: ~/loxodata_text$ cat /opt/pgsql/16/share/tsearch_data/french_custom.syn FISC DGFIP domicile maison auto voiture aimer adorer bosser travailler copain ami joli beau étudiant élève scrameustache alienLe principe étant que le mot situé à gauche sera substitué par celui de droite. Il nous faut donc créer ce dictionnaire de synonymes: loxodata_text=# create TEXT SEARCH DICTIONARY syn_fr (template=synonym, synonyms='french_custom'); CREATE TEXT SEARCH DICTIONARYEt dans la foulée, tester le bon fonctionnement de ce dictionnaire: loxodata_text=# select ts_lexize('syn_fr', 'FISC'); ts_lexize ----------- {dgfip} (1 row) loxodata_text=# select ts_lexize('syn_fr', 'maison'); ts_lexize ----------- (1 row) loxodata_text=# select ts_lexize('syn_fr', 'domicile'); ts_lexize ----------- {maison} (1 row)Il nous reste à modifier le mapping pour les mots afin d’ajouter ce dictionnaire: loxodata_text=# ALTER TEXT SEARCH CONFIGURATION french_custom ALTER MAPPING FOR asciiword WITH syn_fr,french_stem; ALTER TEXT SEARCH CONFIGURATION loxodata_text=# ALTER TEXT SEARCH CONFIGURATION french_custom ALTER MAPPING FOR hword, hword_part, word WITH unaccent,syn_fr, french_stem; ALTER TEXT SEARCH CONFIGURATIONPuis à en vérifier la prise en compte: loxodata_text=# select to_tsvector('french_custom','domicile adoré'); to_tsvector --------------------- 'ador':2 'maison':1 (1 row)C’est moins musical, mais cela fonctionne bien. Limites et dict_xsynLe problème, c’est que le dictionnaire des synonymes passe AVANT le stemmer. Nous avons donc encore affaire à des chaînes de caractères, et non pas des lexèmes. Par conséquent “domicile” et “domiciles” sont des mots différents. On pourrait être tenté de faire passer d’abord le stemmer, puis ensuite le dictionnaire de synonymes, mais cela ne fonctionne pas. L’extension dict_xsyn est livrée en standard et répond (au moins partiellement) à ce problème en permettant de faire un dictionnaire de synonymes plus élaboré. Commençons par créer l’extension: loxodata_text=# create extension if not exists dict_xsyn; CREATE EXTENSIONEnsuite il faut placer un fichier .rules, comme pour le fichier de synonymes: ~/loxodata_text$ cat /opt/pgsql/16/share/tsearch_data/french_custom.rules maison domicile domiciles aimer adore adores adoree adorees adorer adorons adorez adorent DGFIP FISC MINEFI numerique digital ko kb octet byte bytesL’utilisation habituelle de ce fichier est de mettre à gauche un mot, puis ses synonymes à droite. Mais xsyn permet d’inverser ce fonctionnement (la liste de synonymes est la source, et le premier mot est la cible). Là encore, il faut écrire les mots de manière non accentuée puisque unaccent passera AVANT le dictionnaire xsyn. Il faut donc maintenant créer le dictionnaire: loxodata_text=# CREATE TEXT SEARCH DICTIONARY xsyn_fr (template=xsyn_template, rules='french_custom');Faisons un rapide test: loxodata_text=# SELECT ts_lexize('xsyn_fr', 'domicile'); ts_lexize ----------- (1 row) Time: 0,253 ms loxodata_text=# SELECT ts_lexize('xsyn_fr', 'maison'); ts_lexize ---------------------- {domicile,domiciles} (1 row)Le résultat est logique vu notre fichier .rules de synonymes, mais c’est en fait exactement l’inverse du but recherché puisque ce que l’on souhaite c’est que “domicile” et “domiciles” soient transformés en “maison”. Mais comme je l’ai dit, des options booléennes sont disponibles pour les dictionnaires xsyn:
Dans notre cas, nous voulons remplacer par le mot de gauche (original) n’importe quel mot de droite (synonyme), donc:
Il nous reste à modifier les mappings pour le traitement des éléments lexicographiques: loxodata_text=# ALTER TEXT SEARCH CONFIGURATION french_custom ALTER MAPPING FOR asciiword WITH xsyn_fr,french_stem; ALTER TEXT SEARCH CONFIGURATION loxodata_text=# ALTER TEXT SEARCH CONFIGURATION french_custom ALTER MAPPING FOR hword, hword_part, word WITH unaccent,xsyn_fr, french_stem; ALTER TEXT SEARCH CONFIGURATIONEt à tester le fonctionnement: loxodata_text=# select to_tsvector('french_custom','domiciles adorés'); to_tsvector ---------------------- 'aimer':2 'maison':1 (1 row) |
|||||||
Loxodata
|
OpenSource Experience 2024 |
|||||||
Bourgogne-Franche-Comté Publié le mercredi 11 décembre 2024 10h00 Importé le mercredi 11 décembre 2024 13h04 |
LOXODATA était à l’OpenSource Experience 2024L’Open Source Experience (OSXP) 2024 s’est achevée la semaine dernière. LOXODATA était présente à la fois sur le stand des partenaires d’Orange, et comme conférenciers. Nous étions aux côtés d’autres partenaires d’Orange, qui tous proposent leur support et leur expertise autour d’outils open source. Cette présence, en tant que partenaire, nous a permis de communiquer autour de notre expertise PostgreSQL, les prestations, le support ou la formation sur ce fabuleux système de gestion de bases de données et son écosystème. Outre les différentes visites des divisions d’Orange, du TOSIT (The Open Source I Trust) et de certains membres d’OW2, nous avons eu des échanges très enrichissants avec d’autres partenaires et visiteurs. Les possibilités offertes par PostgreSQL attisent toujours autant d’intérêt. Nous remercions Orange pour cette invitation et la visibilité que cela donne à notre entreprise et à leurs partenaires. Côté conférences, nous avons parlé de le sécurisation des accès aux bases de données, une présentation très rapide en 20 minutes d’un vaste sujet. Le support est disponible Sécurisons PostgreSQL . Nous avons également participé au workshop “Orange et ses partenaires dans l’écosystème open source”. |
|||||||
Loxodata
|
PostgreSQL 17.2 et autres correctifs |
|||||||
Bourgogne-Franche-Comté Publié le vendredi 22 novembre 2024 13h00 Importé le vendredi 22 novembre 2024 21h04 |
Le PGDG (PostgreSQL Global Development Group) a publié une mise à jour de toutes les versions supportées de PostgreSQL, incluant 17.2, 16.6, 15.10, 14.15, 13.18. PostgreSQL 12 est maintenant en fin de vie et ne devait plus recevoir de correctifs, mais étant donné la nature d’un problème présent dans la précédente publication, le PGDG (PostgreSQL Global Development Group) publie aussi la version 12.22 de PostgreSQL 12. Les versions 17.1, 16.5, 15.9, 14.14, 13.17, et 12.21 publiées précédemment ne doivent pas être utilisées. Cette publication corrige également 4 vulnérabilités de sécurités et plus de 35 bogues reportés dans les mois précédents. Pour la liste complète des changements, se référer à la section Notes de publication. Note: fin de vie de PostgreSQL 12Il s’agit de la dernière publication de PostgreSQL 12. PostgreSQL 12 est maintenant en fin de vie et ne recevra plus de correctifs de sécurité ou de bogues. Si vous utilisez PostgreSQL 12 en production, nous vous suggérons de planifier une mise à jour vers une version plus récente et supportée de PostgreSQL. Se référer à notre politique de version pour plus d’informations. Correctifs et améliorations de cette publicationLes problèmes ci-dessous concernent PostgreSQL 17. Certains de ces problèmes peuvent toutefois concerner d’autres versions de PostgreSQL. Cette publication:
Problèmes de sécurité
Corrections de bogues et améliorationsCette mise à jour corrige plus de 35 bogues ayant été reportés durant les mois précédents. Les problèmes ci-dessous concernent PostgreSQL 17. Certains de ces problèmes peuvent aussi concerner d’autres versions de PostgreSQL. Les correctifs sont:
Cette publication met aussi à jour les fichiers de fuseau horaire avec la publication de tzdata 2024b. Cette version de tzdata modifie les anciens noms de zones compatibles avec System-V pour dupliquer les zones géographiques correspondantes; par exemple PST8PDT est maintenant un alias pour America/Los_Angeles. La principale conséquence visible est que pour les horodatages antérieurs à l’introduction de fuseaux horaires normalisés, la zone est considérée comme représentant le temps solaire moyen local pour l’emplacement nommé. Par exemple, dans PST8PDT, une entrée timestamptz telle que 1801-01-01 00:00 aurait auparavant été rendue par 1801-01-01 00:00:00-08, mais elle est maintenant rendue par 1801-01-01 00:00:00-07:52:58. Des corrections historiques ont également été apportées pour le Mexique, la Mongolie et le Portugal. Notamment, Asia/Choibalsan est maintenant un alias pour Asia/Ulaanbaatar au lieu d’être une zone séparée, principalement parce que les différences entre ces zones se sont avérées être basées sur des données peu fiables. Mise à jourToutes les publications de mises à jour de PostgreSQL sont cumulatives. Comme pour les autres mises à jour mineures, il n’est pas nécessaire d’extraire et de recharger les bases de données ni d’utiliser pg_upgrade pour appliquer cette mise à jour; il suffit simplement d’arrêter PostgreSQL et de mettre à jour les binaires. Si vous utilisez des tables partitionnées avec des contraintes de clés étrangères pour lesquels vous avez fait des commandes ATTACH PARTITION/DETACH PARTITION, vous allez avoir besoin de faire quelques étapes après cette mise à jour. La correction s’obtient en exécutant une commande ALTER TABLE ... DROP CONSTRAINT sur la table désormais autonome pour chaque contrainte défectueuse, et en ajoutant à nouveau la contrainte. Si l’ajout de la contrainte échoue, vous devez alors rétablir manuellement la cohérence entre les tables référentes et référencées, puis créer à nouveau la contrainte. Cette requête peut être utilisée pour identifier les contraintes défaillantes et construire les commandes pour les recréer: SELECT conrelid::pg_catalog.regclass AS "constrained table" , conname AS constraint , confrelid::pg_catalog.regclass AS "references" , pg_catalog.format('ALTER TABLE %s DROP CONSTRAINT %I;' , conrelid::pg_catalog.regclass , conname) AS "drop" , pg_catalog.format('ALTER TABLE %s ADD CONSTRAINT %I %s;' , conrelid::pg_catalog.regclass , conname , pg_catalog.pg_get_constraintdef(oid)) AS "add" FROM pg_catalog.pg_constraint c WHERE contype = 'f' AND conparentid = 0 AND ( SELECT count(*) FROM pg_catalog.pg_constraint c2 WHERE c2.conparentid = c.oid) <> ( SELECT count(*) FROM pg_catalog.pg_inherits i WHERE (i.inhparent = c.conrelid OR i.inhparent = c.confrelid) AND EXISTS ( SELECT 1 FROM pg_catalog.pg_partitioned_table WHERE partrelid = i.inhparent));Étant donné qu’il est possible qu’une ou plusieurs des étapes ADD CONSTRAINT échouent, vous devriez enregistrer la sortie de cette requête dans un fichier puis exécuter chaque étape. De plus, si vous utilisez PostgreSQL 17.0 et libc comme fournisseur de collation par défaut, et que le paramètre LC_CTYPE vaut C alors que le paramètre LC_COLLATE a une valeur locale différente, vous allez avoir besoin de reconstruire les index basés sur du texte. Vous pouvez faire cela avec la commande REINDEX INDEX CONCURRENTLY. Les utilisateurs ayant sauté une ou plusieurs mises à jour peuvent avoir besoin d’étapes additionnelles après la mise à jour. Les notes de publication des versions précédentes fournissent les détails. Pour plus de détails, se référer à la note de publication de versions. Liens
Si vous avez des corrections ou suggestions sur cette annonce de publication, merci de les envoyer à la mailing liste publique pgsql-www@lists.postgresql.org. |
|||||||
Loxodata
|
Capitole du Libre 2024 |
|||||||
Bourgogne-Franche-Comté Publié le mardi 19 novembre 2024 11h12 Importé le mardi 19 novembre 2024 13h04 |
Retour sur le week-end du Capitole du LibreLe week-end du 16 et 17 novembre 2024 s’est tenue l’édition 2024 du Capitole du Libre. Ce rendez-vous incontournable du logiciel libre à Toulouse s’est déroulé au sein de l’ENSEEIHT. LOXODATA a proposé des présentations qui ont été acceptées (merci au comité de sélection) parmi un large panel de conférences et ateliers dont vous retrouverez le programme complet ici. Parmi les propositions de LOXODATA, vous pouviez voir les sujets suivants:
Une captation vidéo a été effectuée et devrait être mise en ligne prochainement. Merci à l’équipe de bénévoles pour l’organisation et à l’ENSEEIHT pour l’accueil de l’évènement. Rendez-vous l’année prochaine pour une autre édition. |
|||||||
Loxodata
|
Capitole du libre 2024 |
|||||||
Bourgogne-Franche-Comté Publié le lundi 04 novembre 2024 10h45 Importé le lundi 04 novembre 2024 13h05 |
Le Capitole du libre 2024 nous offre un weekend d’échanges autour du logiciel libre à Toulouse au sein de l’ENSEEIHT les 16 et 17 novembre prochains. Le programmeVous pouvez retrouver le programme complet ici de l’édition de cette année. Avec une centaine de conférences et près de 25 ateliers, en plus de keynotes et du village associatif, ce weekend s’annonce riche en partage autour du logiciel libre. Le Capitole du libre est organisé depuis 2009 par l’association Toulibre. Cette année, LOXODATA s’est porté partenaire Bronze de l’évènement, avec la présentation de quatres conférences, dont une en partenariat avec le groupe Orange:
L’évènement est gratuit mais il est nécessaire de s’inscrire ici. Crédits photo: Baptiste Buisson, Toulibre, Capitole du Libre |
|||||||
Loxodata
|
Capitole du libre 2024 |
|||||||
Bourgogne-Franche-Comté Publié le lundi 04 novembre 2024 10h45 Importé le mardi 19 novembre 2024 13h04 |
Le Capitole du libre 2024 nous offre un weekend d’échanges autour du logiciel libre à Toulouse au sein de l’ENSEEIHT les 16 et 17 novembre prochains. Le programmeVous pouvez retrouver le programme complet ici de l’édition de cette année. Avec une centaine de conférences et près de 25 ateliers, en plus de keynotes et du village associatif, ce weekend s’annonce riche en partage autour du logiciel libre. Le Capitole du libre est organisé depuis 2009 par l’association Toulibre. Cette année, LOXODATA s’est porté partenaire Bronze de l’évènement, avec la présentation de quatres conférences, dont une en partenariat avec le groupe Orange:
L’évènement est gratuit mais il est nécessaire de s’inscrire ici. Crédits photo: Baptiste Buisson, Toulibre, Capitole du Libre |
|||||||
Loxodata
|
PostgreSQL 17 |
|||||||
Bourgogne-Franche-Comté Publié le vendredi 27 septembre 2024 10h00 Importé le vendredi 27 septembre 2024 13h05 |
Sortie de PostgreSQL 1726 septembre 2024 - Le PostgreSQL Global Development Group annonce aujourd’hui la publication de PostgreSQL 17, dernière version de la base de données open source de référence. PostgreSQL 17 repose sur plusieurs décennies de développement, améliorant ses performances et sa mise à l'échelle tout en s’adaptant aux modèles émergents d’accès aux données et à leur stockage. Cette version de PostgreSQL amène des gains de performance généralisés, dont une révision complète de l’implantation de la gestion de la mémoire des opérations de vacuum, des optimisations de l’accès au stockage, des améliorations pour les charges de travail fortement concurrentielles, l’accélération des chargements et exports en masse et des améliorations de l’exécution des requêtes utilisant les index. PostgreSQL 17 possède des fonctionnalités qui profitent aussi bien aux nouvelles charges de travail qu’aux systèmes critiques. On peut citer les ajouts à l’expérience développeur avec la commande SQL/JSON JSON_TABLE et les améliorations de réplication logique qui simplifient la gestion de la haute disponibilité et des mises à jour de version majeures. «PostgreSQL 17 souligne la manière dont la communauté open source mondiale, qui pilote le développement de PostgreSQL, construit les améliorations qui aident les utilisateurs à tous les niveaux de leur expérience avec la base de données» dit Jonathan Katz, un membre de la «core team» de PostgreSQL. «Qu’il s’agisse d’améliorations pour opérer les bases de données à l'échelle ou de nouvelles fonctionnalités qui contribuent à une expérience développeur agréable, PostgreSQL va parfaire votre expérience de la gestion de données. » PostgreSQL, système innovant de gestion des données, reconnu pour sa fiabilité et sa robustesse, bénéficie depuis plus de 25 ans d’un développement open source par une communauté mondiale de développeurs et développeuses. Il est devenu le système de gestion de bases de données relationnelles de référence pour les organisations de toute taille. Des gains de performance sur l’ensemble du moteurLe processus de vacuum de PostgreSQL, critique pour le bon déroulement des opérations, nécessite des ressources du serveur de l’instance pour s’exécuter. PostgreSQL 17 introduit une nouvelle structure interne de la mémoire pour vacuum qui divise par 20 l’utilisation mémoire. PostgreSQL améliore ainsi la vitesse des opérations de vacuum tout en réduisant l’usage des ressources partagées, les rendant disponibles à votre charge de travail. PostgreSQL 17 poursuit l’amélioration des performances de sa couche d’entrées/sorties. Les charges de travail hautement concurrentes pourront voir leurs performances en écriture doubler grâce à une amélioration sur le traitement du write-ahead log (WAL). De plus, la nouvelle interface d’entrées/sorties par flux accélère les lectures séquentielles (lecture de toutes les données d’une table). Cette même fonctionnalité bénéficie aussi à ANALYZE qui peut ainsi mettre à jour les statistiques du planificateur de requêtes bien plus rapidement. PostgreSQL 17 étend ses gains de performance à l’exécution de requêtes. Il améliore la performance des requêtes avec des clauses IN utilisant des index de type B-tree, la méthode d’indexation par défaut de PostgreSQL. De plus, il est maintenant possible de paralléliser la construction des index BRIN. PostgreSQL 17 comporte plusieurs améliorations dans la planification des requêtes, dont des optimisations sur les contraintes NOT NULL et des améliorations dans le traitement des common table expressions (les requêtesWITH). Cette version prend en charge plus d’instructions SIMD (Single Instruction/Multiple Data) pour accélérer les calculs, incluant l’usage d’AVX-512 pour la fonction bit_count. Amélioration pour les développeursPostgreSQL a été la première base de données relationnelle à ajouter le support de JSON (2012), et PostgreSQL 17 complète son implantation du standard SQL/JSON. JSON_TABLE est maintenant disponible dans PostgreSQL 17, permettant aux développeurs de convertir des données JSON dans une table standard PostgreSQL. PostgreSQL 17 supporte maintenant les constructeurs SQL/JSON (JSON, JSON_SCALAR, JSON_SERIALIZE) et les fonctions de requêtage (JSON_EXISTS, JSON_QUERY, JSON_VALUE), offrant de nouvelles possibilités aux développeurs d’interagir avec leurs données JSON. Cette version ajoute plus d’expressions jsonpath, avec un accent sur la conversion de données JSON vers des types de données natifs de PostgreSQL comme les types numériques, booléens, chaînes de caractères et date/heure. PostgreSQL 17 rajoute des fonctionnalités à la commande MERGE, utilisée pour les mises à jour conditionnelles, en incluant une clause RETURNING et la capacité de mettre à jour les vues. En prime, PostgreSQL 17 dispose de nouvelles capacités de chargement et d’export de données en masse pouvant aller jusqu'à doubler la performance lors de l’export de grandes lignes en utilisant la commande COPY. COPY bénéficie d’améliorations de performance, lorsque les encodages de la source et de la destination correspondent et inclut une nouvelle option, ON_ERROR, qui permet la poursuite d’un import même en cas d’erreur d’insertion. Cette version étend les fonctionnalités de gestion des données à la fois dans les partitions et dans les données distribuées sur des instances PostgreSQL distantes. PostgreSQL 17 supporte l’utilisation de colonnes identité et des contraintes d’exclusions sur des tables partitionnées. Les foreign data wrapper PostgreSQL (postgres_fdw), qui sont utilisés pour exécuter des requêtes sur des instances PostgreSQL distantes, peuvent maintenant transmettre les sous-requêtes EXISTS et IN vers un serveur distant pour un traitement plus efficace. PostgreSQL 17 inclut un fournisseur de collation interne, indépendant de la plateforme et immutable permettant de garantir l’immutabilité des résultats et fournit une sémantique de tri similaire à la collation C mais avec l’encodage UTF-8 au lieu de SQL_ASCII. L’utilisation de ce nouveau fournisseur de collation garantit que les résultats triés des requêtes basées sur du texte seront identiques, indépendamment de l’environnement. Améliorations de la réplication logique pour la haute disponibilité et les mises à jour majeuresLa réplication logique est utilisée pour transmettre des données en temps réel dans de nombreux cas d’usage. Toutefois, avant cette version, une mise à jour majeure nécessitait de supprimer les slots de réplication logique, ce qui obligeait à resynchroniser les données vers les souscripteurs après la mise à jour. À partir de PostgreSQL 17, les mises à jour utilisant la réplication logique seront simplifiées: elles ne nécessiteront plus de supprimer les slots de réplication logique. PostgreSQL 17 inclut désormais un contrôle des bascules sur incident pour la réplication logique, ce qui la rend plus résiliente dans les environnements hautement disponibles. Enfin, PostgreSQL 17 introduit l’outil en ligne de commande pg_createsubscriber pour convertir un réplica physique en réplica logique. Autres options de gestion de la sécurité et des opérations de maintenancePostgreSQL 17 étend les possibilités de gestion du cycle de vie des systèmes de bases de données. Une nouvelle option TLS, sslnegotiation, est ajoutée, qui permet aux utilisateurs d’effectuer une négociation TLS directe lors de l’utilisation d’ALPN (enregistrée comme postgresql dans le répertoire ALPN). PostgreSQL 17 ajoute le rôle prédéfini pg_maintain, qui donne les privilèges d’effectuer des opérations de maintenance aux utilisateurs. pg_basebackup, l’utilitaire de sauvegarde intégré à PostgreSQL, supporte désormais les sauvegardes incrémentales et ajoute l’utilitaire pg_combinebackup pour reconstruire une sauvegarde complète. En complément, pg_dump intègre une nouvelle option, appelée --filter, qui permet de préciser un fichier contenant la liste des objets à intégrer lors de la génération d’un export. PostgreSQL 17 ajoute des améliorations aux fonctionnalités de supervision et d’analyse. EXPLAIN présente maintenant le temps passé sur les lectures et écritures de blocs et intègre deux nouvelles options: SERIALIZE et MEMORY, utiles pour voir le temps passé dans la conversion de données lors des transmissions réseau, et la quantité de mémoire utilisée. PostgreSQL 17 indique désormais la progression du vacuum des index. Cette version ajoute la vue système pg_wait_events, qui combinée avec pg_stat_activity, donne plus d’informations sur les raisons pour lesquelles une session active est en attente. Fonctionnalités additionnellesDe nombreuses autres fonctionnalités ont été ajoutées à PostgreSQL 17. Elles peuvent aussi être utiles dans vos cas d’usage. Vous pouvez vous référer aux notes de version (en anglais) pour consulter la liste complète des fonctionnalités modifiées ou ajoutées. À propos de PostgreSQLPostgreSQL est le système de gestion de bases de données libre de référence. Sa communauté mondiale est composée de plusieurs milliers d’utilisateurs, utilisatrices, contributeurs, contributrices, entreprises et institutions. Le projet PostgreSQL, démarré il y a plus de 30 ans à l’université de Californie, à Berkeley, a atteint aujourd’hui un rythme de développement sans pareil. L’ensemble des fonctionnalités proposées est mature, et dépasse même celui des systèmes commerciaux leaders sur les fonctionnalités avancées, les extensions, la sécurité et la stabilité. Liens
En savoir plus sur les fonctionnalitésPour de plus amples informations sur les fonctionnalités ci-dessus et toutes les autres, vous pouvez consulter les liens suivants: Où téléchargerIl existe plusieurs façons de télécharger PostgreSQL 17, dont:
D’autres outils et extensions sont disponibles sur le PostgreSQL Extension Network. DocumentationLa documentation au format HTML et les pages de manuel sont installées avec PostgreSQL. La documentation peut également être consultée en ligne ou récupérée au format PDF. LicencePostgreSQL utilise la licence PostgreSQL, licence «permissive» de type BSD. Cette licence certifiée OSI est largement appréciée pour sa flexibilité et sa compatibilité avec le monde des affaires, puisqu’elle ne restreint pas l’utilisation de PostgreSQL dans les applications propriétaires ou commerciales. Associée à un support proposé par de multiples sociétés et une propriété publique du code, sa licence rend PostgreSQL très populaire parmi les revendeurs souhaitant embarquer une base de données dans leurs produits sans avoir à se soucier des prix de licence, des verrous commerciaux ou modifications des termes de licence. ContactsSite internet Courriel
Images et logosPostgres, PostgreSQL et le logo éléphant (Slonik) sont des marques déposées de l’Association de la Communauté PostgreSQL. Si vous souhaitez utiliser ces marques, vous devez vous conformer à la politique de la marque. Support professionnel et donsPostgreSQL bénéficie du support de nombreuses sociétés, qui financent des développeurs et développeuses, fournissent l’hébergement ou un support financier. Les plus fervents supporters sont listés sur la page des sponsors. Il existe également une très grande communauté de sociétés offrant du support PostgreSQL, du consultant indépendant aux entreprises multinationales. Les dons au PostgreSQL Global Development Group, ou à l’une des associations à but non lucratif, sont acceptés et encouragés. Crédits photo Richard Jacobs. |
|||||||
Loxodata
|
PGConf.EU 2024 à Athènes |
|||||||
Bourgogne-Franche-Comté Publié le mercredi 18 septembre 2024 15h30 Importé le mercredi 18 septembre 2024 21h04 |
Cette année encore, LOXODATA participera à la PGConf Europe 2024 qui se tiendra du 22 au 25 octobre au Divani Caravel Hotel à Athènes. LOXODATA sera partenaire Bronze de l'évènement. La conférence reprend le format habituel d’une journée de formations, suivi de trois journées de présentations réparties sur trois salles en parallèle. Il est toujours possible de s’inscrire à l'évènement. Ce sera la quatorzième année consécutive que se déroule la PGConf Europe, hormis les années 2020 et 2021 pour les raisons que l’on connaît tous. C’est l’occasion pour tous les acteurs du projet PostgreSQL de se rencontrer et partager, quel que soit son niveau et l’utilisation que l’on peut avoir de PostgreSQL. Le programmeVous pouvez retrouver le programme de l'évènement sur le site de la conférence. Magnus Hagander en maître de conférence initiera l'évènement avec un talk de bienvenue, puis laissera place à Stacey Haysler pour une présentation générale sur PostgreSQL, là où l’année dernière Simon Riggs nous faisait la rétrospective des vingt dernières années du projet PostgreSQL et perspectives des vingt prochaines années. Puis, vous aurez à loisir de choisir parmi une cinquantaine de présentations sur des sujets divers: techniques, communautaires ou grand public. Nous espérons vous retrouver dans les allées de cette prochaine PGConf Europe 2024 afin de partager cet évènement annuel important pour la communauté PostgreSQL en Europe. Crédits photo: Kylie Docherty et PostgreSQL Europe |
|||||||
Loxodata
|
PostgreSQL 17 en RC1 |
|||||||
Bourgogne-Franche-Comté Publié le vendredi 06 septembre 2024 12h00 Importé le vendredi 06 septembre 2024 13h04 |
Le PostgreSQL Global Development Group a annoncé la publication de la première Release Candidate de PostgreSQL 17. En tant que Release Candidate, la version de PostgreSQL 17 RC1 sera quasiment identique à la publication initiale de PostgreSQL 17, cependant, des corrections pourront être appliquées avant la mise à disposition de la version finale de PostgreSQL 17. La date de publication pour la version finale de PostgreSQL 17 est prévue au 26 septembre 2024. Consulter la section Planning des publications pour plus de détails. Mise à jour vers la RC1 de PostgreSQL 17Pour mettre à jour votre version de PostgreSQL depuis une précédente version de PostgreSQL, vous pouvez utiliser la même stratégie que pour mettre à jour vers toute version majeure de PostgreSQL (par exemple avec la commande pg_upgrade ou pg_dump/pg_restore). Pour plus d’information, consultez la section mise à jour de la documentation officielle: https://www.postgresql.org/docs/17/upgrading.html Changements depuis la bêta 3Plusieurs corrections ont été apportées à PostgreSQL 17 suite aux remontées d’utilisateurs ayant testé la bêta 3. Dont notamment:
Pour la liste complète des corrections, veuillez consulter la page des tickets ouverts. Planning des publicationsIl s’agit de la première Release Candidate de la version 17. Sauf à découvrir un problème imposant un nouveau délai ou une nouvelle Release Candidate, PostgreSQL 17 devrait être publiée le 26 septembre 2024. Pour plus d’information, veuillez consulter la page Beta Testing. Liens |
|||||||
Voir plus |