Quoi de neuf coté PostgreSQL ?

Je prof­ite de deux arti­cles que je viens de lire (GNU/Linux Mag­a­zine n°198 et 201) sur Post­greSQL et de quelques post pêchés sur le web pour vous faire une petite syn­thèse des avancées de Post­greSQL depuis la ver­sion 9.6 (on par­lera un peu des autres quand même).

Dans ma vielle tech­no, il y a une page réservée à Post­greSQL. Elle évolue avec les ver­sions et selon mes recherch­es et travaux.

Bon, je ne vous présente pas Post­greSQL, il s’ag­it d’un SGBDR de type objet. C’est prob­a­ble­ment la meilleure base poly­va­lente de don­nées Open Source aujour­d’hui. Après, je ne par­le pas de Big­Da­ta et de NoSQL. C’est une sorte de con­cur­rent de DB2, d’O­r­a­cle, de Microsoft SQL Serv­er et de Mari­aDB… Mais en réal­ité, ça dépend forte­ment des besoins. Bon, ça donne quoi Post­greSQL aujour­d’hui ? Je dois vous avouer que je l’ai util­isé inten­sé­ment il y a quelques années (sans devenir une poin­ture non plus… mais dans le cadre de développe­ments d’ap­pli­ca­tion) et je n’ai pas trop suivi les évo­lu­tions. Les voici…

Parallélisme / Multi-CPU

La prin­ci­pale avancée qu’on attendait depuis plusieurs années est le par­al­lélisme, c’est à dire, la pos­si­bil­ité d’u­tilis­er mas­sive­ment (et intel­ligem­ment) les mul­ti­ples processeurs d’une machine. Bon, quand on a un serveur avec 4 processeurs, c’est pas for­cé­ment fla­grant, mais si on dis­pose d’une cen­taine de processeurs, ça devient car­ré­ment impératif.  Pourquoi cela a t‑il mis si longtemps ? Il faut savoir qu’à la base Post­greSQL est un sys­tème mul­ti-proces­sus et non mul­ti-threads. Je vous rap­pelle la dif­férence: A la dif­férence des proces­sus, les threads partage le même espace mémoire pro­tégé, les mêmes ressources et le même espace mémoire. De fait, si on a plusieurs proces­sus, il faut établir des zones spé­ci­fiques de mémoire partagée, c’est pas évi­dent. En même temps, du mul­ti-thread, c’est dan­gereux car si un thread plante ou fait une mau­vaise manip en mémoire, les autres trin­quent aus­si. Bref, c’est plus facile de faire du mul­ti-proces­sus que du mul­ti-threads car c’est moins dan­gereux.

Post­greSQL utilise donc plusieurs proces­sus, pour l’écri­t­ure en tâche de fond, pour la main­te­nance, la répli­ca­tion, etc. Mais voilà, si on a un ordi­na­teur avec plusieurs CPU, un seul sera util­isé pour votre requête. Si la base est util­isée par de nom­breux util­isa­teurs, ce n’est pas un soucis, la charge se répar­ti. Mais c’est quand même dom­mage de ne pas pou­voir exé­cuter une même requête sur plusieurs processeurs. C’est chose faite, en tous cas, c’est en très bonne voie, avec la ver­sion 9.6.

Pour faire cela, il y avait 2 pos­si­bil­ités: soit opter pour du mul­ti-threads avec les impli­ca­tions dont nous avons déjà par­lé, soit per­me­t­tre aux proces­sus de deman­der de l’aide d’autres proces­sus. On les appel­era les “work­ers” — oui, c’est bien la sec­onde solu­tion qui a été retenue. En ver­sion 9.6, seules les requêtes en lec­ture pour­ront être par­al­lélisées (sauf les tables tem­po­raires). On peut étudi­er la façon dont les requêtes sont par­al­lélisées en visu­al­isant le Query Plan au tra­vers de la com­mande Explain. Le niveau de par­al­léli­sa­tion est indiqué par deux lignes: work­ers planned et work­ers launched:

Je vous passe le fait qu’il est pos­si­ble de paramétr­er cela, voir même de spé­ci­fi­er par table le nom­bre de work­ers sug­gérés. Mais le moteur s’en charge très bien lui-même et estime quelques fois qu’une par­al­léli­sa­tion est coû­teuse et inutile. Bref, la par­al­léli­sa­tion apporte, vous l’au­rez com­pris, un gain de per­for­mance plus ou moins impor­tant selon le serveur.

SQL/MED

La ver­sion 8.3 a vu la mise en place d’une infra­struc­ture SQL/MED ( Man­age­ment of Exter­nal Data). C’est une exten­sion à SQL définie en 2003 offrant moyen à un SGBDR d’ac­céder à des don­nées qu’il ne gère pas — à des tables externes par exem­ple. Imag­inez que vous dévelop­piez une appli­ca­tion pour la ges­tion de votre entre­prise: il vous faut taper dans des don­nées de ventes sous Ora­cle, des don­nées du site web sous Pos­greSQL et d’autres dans une base Informix par exem­ple .Grâce à un con­necteur, For­eign Data Wrap­per, il vous est pos­si­ble d’in­ter­roger votre base Post­greSQL con­cer­nant des don­nées qui sont ailleurs… per­me­t­tant ain­si de faire des join­tures et tout un tas d’autres trucs. Et pourquoi pas avec des bases NoSQL égale­ment.

Les tables externes sont apparues avec la ver­sion 9.1, mais elles n’é­taient qu’en lec­ture seule. La ver­sion 9.3 a vu arriv­er la pos­si­bil­ité d’écrire dans ces tables. Enfin, la ver­sion 9.5 a per­mis la créa­tion automa­tique des tables d’une source dis­tante. Mais c’est avec la 9.6 qu’ont été mis­es en place de nom­breuses amélio­ra­tions, notam­ment au niveau des join­tures. Quand cela est pos­si­ble, une join­ture de deux tables externes est réal­isée par le SGBD externe avant d’en­voy­er le résul­tat. En 9.5, ce n’é­tait pas le cas, la join­ture était réal­isée en locale, en impor­tant en quelques sortes les deux extraits de table… d’où un gain de per­for­mance impor­tant aujour­d’hui. De même, l’écri­t­ure dans des tables externes, les updates, les delete… tout cela est réal­isé à dis­tance. Bon, bien sûr, tout dépend du Wrap­per ! Pour Ora­cle et Post­greSQL, ça fonc­tionne par­faite­ment. Mais pour les autres, ça va dépen­dre des développeurs de ces mêmes wrap­pers.

Réplication

La répli­ca­tion, c’est le fait de pou­voir utilis­er plusieurs bases des don­nées syn­chro­nisées entre elles… bon, je n’ai pas une bonne déf­i­ni­tion en tête, alors voici un exem­ple: vous avez une base de don­nées de clients et votre com­mer­cial part avec son portable dans une zone non-cou­verte et ne peut donc pas se con­necter à dis­tance. Il va utilis­er une base de don­nées locale. Cette base sera à jour si un mécan­isme de répli­ca­tion a per­mis de syn­chro­nis­er les dif­férentes tables avant qu’il ne parte en tournée. On par­lera sou­vent d’une base maître (ou par­ente) et de bases esclaves (ou enfants) — bien qu’il existe des mécan­ismes plus com­plex­es où il n’y a pas de notion de pri­or­ité aus­si sim­pliste.

On par­le de répli­ca­tion bi-direc­tion­nelle si on veut que les bases enfants puis­sent égale­ment envoy­er des mod­i­fi­ca­tions à la base par­ente, avec tous les con­flits que cela peut pro­duire — d’où une ges­tion de con­flits à met­tre en place, avec des pri­or­ités à régler. On par­le de répli­ca­tion syn­chrone quand les bases sont con­nec­tées et que les mod­i­fi­ca­tions sont immé­di­ate­ment pris­es en compte, ou asyn­chrone quand il peut s’é­couler un délai, comme dans le cas de notre com­mer­cial. On par­le aus­si de répli­ca­tion jour­nalée.

J’avais bossé sur le cas d’une répli­ca­tion bi-direc­tion­nelle et asyn­chrone il y a quelques années, alors qu’au­cun mécan­isme de répli­ca­tion n’é­tait inté­gré au sein de Post­greSQL. J’avais util­isé pour cela une librairie écrite en Ruby dont j’ai oublié le nom (rubyrep prob­a­ble­ment). Mais le cas était assez com­pliqué et la solu­tion avec un fichi­er de répli­cats (comme sous Windev avec Hyper­file) n’é­tait pas vrai­ment top.  Mais ça fonc­tion­nait… lente­ment, mais sûre­ment.

La solu­tion interne de répli­ca­tion de Post­greSQL est aujour­d’hui une solu­tion asymétrique:  un serveur maître (on dit “pri­maire”, c’est plus pro) per­met l’écri­t­ure, mais les sec­ondaires (les esclaves… les enfants, vous voyez) ne per­me­t­tent que la lec­ture — pas de con­flit ain­si. C’est une solu­tion asyn­chrone, bien qu’il soit pos­si­ble de la ren­dre syn­chrone en le paramé­trant. C’est au niveau des serveurs syn­chrones qu’il y a le plus d’op­ti­mi­sa­tions avec la 9.6.

Divers

Ce qui me plait ien aus­si avec la ver­sion 9.6, c’est la pos­si­bil­ité de rechercher des phras­es (full­text search) dans une base de don­nées. Imag­inez que vous index­iez des doc­u­ments d’une GED. Vous exportez tous les docs dans une ver­sion TXT stock­ée dans une table. Et vous voulez faire un moteur de recherche type Apache Lucene. Désor­mais, vous pou­vez lancer des requêtes en indi­quant le texte à rechercher, mais aus­si le nom­bre de mots entre 2 mots clés, etc. En effet, avant la 9.6, on pou­vait chercher les doc­u­ments con­tenant 2 mots clés ou plus, mais pas qui se suiv­ent. Pour ce faire, il fal­lait utilis­er des iLike et c’é­tait coû­teux en ressources. Aujour­d’hui, non seule­ment on peut le faire, mais aus­si indi­quer le nom­bre max de mots inter­mé­di­aires (opéra­teur <-> ou <n> avec n le nom­bre de mots) — ce qui dans un doc­u­ment com­plet de plusieurs pages change bien la donne.  Bon, pour la mise en pra­tique, suiv­ez ce lien.

Voilà, il y a d’autres opti­mi­sa­tions comme au niveau des VACUUM FREEZE, des CHECKPOINT, du GROUP BY … de la ges­tion du cache des écri­t­ures, de la sauve­g­arde PITR et même au niveau de l’admin­is­tra­tion, mais je vous laisse décou­vrir cette liste sur cette page, ce sera plus sim­ple.

Ce que je retiens, c’est cette indi­ca­tion de la pro­gres­sion d’une com­mande qui com­mence à poindre du nez. Cela ne fonc­tionne que pour le VACUUM pour l’in­stant (et pas le full), mais c’est le début et y‑a fort à pari­er que toutes les com­man­des finiront par en béné­fici­er. Imag­inez que vous lan­ciez une longue requête et qu’en temps-réel vous pou­vez savoir où ça en est ! Un peu comme quand on copie un fichi­er en quelques sortes. Même si l’in­for­ma­tion est plus ou moins heuris­tique, ce sera un bon indi­ca­teur pour aider à patien­ter — mais aus­si pour savoir si on fait pas d’autres choses en même temps — le pro­gramme, pas vous… j’imag­ine que vous avez une main sur la souris et une autre sur la tassé de café 😉 Bref, plus de pos­si­bil­ités pour le développeur !

Une autre fonc­tion­nal­ité intéres­sante c’est la pos­si­bil­ité d’obtenir plus de détails sur une ses­sion blo­quée (dans la table pg_stat_activity).

Quid de la version 10 ?

Il sem­blerait qu’un véri­ta­ble sup­port pour le par­ti­tion­nement de table sera implé­men­té ! Le par­ti­tion­nement fait référence à la divi­sion d’une table volu­mineuse en plusieurs tables plus petites, appelées par­ti­tions. Cela per­met d’amélior­er la ges­tion, la per­for­mance des tables ou la disponi­bil­ité des don­nées. Chaque par­ti­tion se retrou­ve sur des serveurs ou des dis­ques dif­férents. Cela per­met égale­ment d’obtenir une capac­ité de base de don­nées supérieure à la taille max­i­mum des dis­ques durs ou d’effectuer des requêtes en par­al­lèle sur plusieurs par­ti­tions. C’est la notion de shard­ing ou de dis­tri­b­u­tion des don­nées.

Post­greSQL offre déjà un sup­port du par­ti­tion­nement de tables, mais il s’agit d’un sup­port basique à tra­vers l’héritage de tables. Pas très pra­tique. Avec le par­ti­tion­nement natif, tout sera réal­isé en arrière-plan, il n’y aura pas besoin de gér­er un tas de choses. Il suf­fi­ra de déclar­er com­ment une table doit être par­ti­tion­née, sans devoir implé­menter les détails. Avec Ora­cle par exem­ple, la table par­ti­tion­née est vue par le développeur comme une unique table, mais comme plusieurs par le moteur Ora­cle.

Conclusion

Voilà, très intéres­santes ces nou­velles fonc­tion­nal­ités, et il reste encore beau­coup de choses à venir avec la ver­sion 10. On sent aus­si avec le par­ti­tion­nement la pres­sion faite par le Big Data sur l’ensem­ble des SGBD. Aujour­d’hui, tout est affaire de Big Data pour le stock­age et de Deep Learn­ing pour la com­préhen­sion des don­nées… ne passez pas à coté, même si vous êtes dans le jeu vidéo !

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.