Redonner du tonus à Jean des Pois Verts ?
Dans cette deuxième partie consacrée aux index BRIN nous avons vu quils nétaient pas adaptés dans tous les cas. Mais, même dans les cas oû ils sont adaptés, que se passe-t-il lorsque les données indexées sont modifiées ?
Le principe dun index BRIN est de stocker la valeur minimale et la valeur maximale pour une colonne dans un ensemble de lignes stockées dans N pages. Si la valeur de la colonne indexée est modifiée pour une ligne plusieurs cas se présentent :
Revenons sur le dernier point. Supposons que la valeur minimale dans une colonne de type SMALLINT pour un ensemble de pages soit 2, la valeur maximale 10. Pour une des lignes la valeur dans la colonne qui était à 10 passe à 5. La nouvelle valeur maximale nest pas forcément devenue 5. Il peut rester des lignes dans lensemble de pages pour lesquelles la colonne indexée a pour valeur 6, 7, 8, 9 ou encore 10 sil ny a pas de contrainte dunicité sur cette colonne.
Il y avait donc ici un choix à faire pour les concepteurs de PostgreSQL. Fallait-il sacrifier la vitesse de mise à jour ou la pertinence de lindex ?
Pour comprendre ce qui a été choisi nous allons reprendre la table VENTES de la première partie et lui ajouter une colonne ID de type INTEGER GENERATED AS IDENTITY (valeur entière autoincrémentée). La colonne DTV sera mise à jour pour chaque ligne en diminuant sa valeur de 2 fois ID secondes. Cela na aucun sens fonctionnel mais cela renversera complètement lordre de tri de la colonne DTV par rapport à lordre dinsertion. Les données seront au final toujours triées selon leur ordre dinsertion initial mais de manière décroissante au lieu de croissante. La colonne DTV est donc toujours une bonne candidate même après mise à jour mais lindex BRIN sera-t-il toujours pertinent sans intervention explicite au niveau de lindex ?
Illustration avec PostgreSQL 10 en faisant une comparaison avec le comportement dun index B-Tree :
Que pouvons-nous constater ?
Tout d'abord, la présence de lindex BRIN a nettement moins ralenti la mise à jour que la présence de lindex B-Tree : 2min48s contre 4min59s.
Les index B-Tree nécessitent rarement dêtre reconstruits, bien quil existe des cas très précis où une réindexation est bénéfique. Après mise à jour, lors dune recherche portant toujours sur une plage de 14 jours sur 365, lindex B-Tree conserve ici toute son efficacité avec des temps d'exécution restant sous la demi-seconde.
En revanche lindex BRIN perd complètement son efficacité après l'update. Les temps dexécution passent de moins de 1 seconde à 14 secondes. Après réindexation, lindex BRIN retrouve cependant son efficacité initiale avec des temps d'exécution repassant sous la seconde. A noter quun VACUUM de la table, manuel ou réalisé automatiquement par AUTOVACUUM, recalcule également les min/max évoqués précédemment et a donc le même effet positif.
La vitesse de mise à jour a donc été privilégiée par rapport à la pertinence de lindex BRIN. Il convient donc, après une mise à jour importante affectant une colonne indexée par un Block Range Index, de considérer une réindexation voire une suppression de lindex. En effet, dans lexemple fourni, la colonne DTV est toujours candidate a une indexation BRIN mais une mise à jour pourrait très bien entraîner le cas présenté dans la deuxième partie. Le DBA peut donner lalerte mais il est déjà trop tard si un probléme dindexation entraînant une perte de performance est découvert en production. Lindexation nécessite une connaissance fonctionnelle et doit avoir été réfléchie au niveau du développement.