PostgreSQLLa base de données la plus sophistiquée au monde.
Documentation PostgreSQL 15.10 » Internes » Index BRIN » Introduction

71.1. Introduction

BRIN signifie Block Range Index, soit index par intervalles de bloc. BRIN est conçu pour gérer de grosses tables dont certaines ont des colonnes ayant une corrélation naturelle avec leur stockage physique.

BRIN fonctionne en terme d'intervalle de blocs (ou « intervalle de pages »). Un intervalle de bloc est un groupe de blocs physiquement adjacents dans la table ; Pour chaque gamme de bloc, un résumé des informations est stocké par l'index. Un exemple courant est une table avec une colonne date, contenant les références des ventes d'un magasin. Chaque commande y serait enregistrée chronologiquement. Dans la plupart des cas, les données seront donc insérées dans le même ordre où elles apparaîtront par la suite. De la même manière, une table, avec une colonne code postal, pourrait avoir tous les codes d'une même ville rassemblés naturellement au même endroit.

Les index BRIN peuvent répondre à des requêtes via un parcours d'index bitmap classique, et retourneront toutes les lignes de toutes les pages dans chaque intervalle si le résumé des informations contenues dans l'index est cohérent avec les conditions de la requête. L'exécuteur de la requête doit revérifier ces lignes et annuler celles qui ne répondent pas aux conditions initiales de la requête. En d'autres termes, on parle d'index à perte (lossy). Comme l'index BRIN est un petit index, parcourir cet index ajoute une légère surcharge par rapport à un parcours séquentiel mais permet d'éviter de parcourir des grandes parties de la table où on sait qu'on ne trouvera pas de lignes à remonter.

Les données spécifiques qu'un index BRIN va stocker, de même que les requêtes spécifiques auquel l'index va pouvoir répondre dépendent de la classe d'opérateur choisie pour chaque colonne de l'index. Les types de données possédant un ordre de tri linéaire peuvent utiliser une classe d'opérateur qui ne conserve que la valeur minimale et la valeur maximale dans chaque intervalle de bloc. Par exemple, un type géométrique peut stocker une bounding box pour tous les objets de l'intervalle de bloc.

La taille de l'intervalle de bloc est déterminée à la création de l'index par le paramètre pages_per_range Le nombre des entrées de l'index sera égal à la taille de la relation en page, divisée par la valeur sélectionnée dans pages_per_range. De ce fait, plus ce nombre est bas, plus l'index sera volumineux (il y a plus d'entrées d'index à stocker) mais, en même temps, le résumé des informations stockées pourra être plus précis, et un nombre plus important de blocs de données pourront être ignorés pendant le parcours d'index.

71.1.1. Maintenance de l'index

Lors de la création de l'index, toutes les pages de la table sont parcourues et un résumé des lignes de l'index est créé pour chaque intervalle, incluant certainement aussi un intervalle incomplet à la fin. Lors de l'ajout de nouvelles données dans des pages déja incluses dans des résumés, cela va entrainer la mise à jour du résumé, avec les informations sur les nouvelles lignes insérées. Lorsqu'une nouvelle page est créée et qu'elle ne correspond à aucun des derniers intervalles résumés, l'intervalle auquel appartient la nouvelle page n'acquiert pas automatiquement un résumé ; ces lignes restent sans résumé jusqu'à ce qu'une exécution de résumé soit demandée plus tard, créant ainsi le résumé initial pour cet intervalle.

Il existe plusieurs façons de déclencher le résumé initial d'un intervalle de blocs. Si la table est traitée par VACUUM, soit manuellement soit par l'autovacuum, tous les intervalles de blocs existants non résumés sont résumés. De plus, si le paramètre autosummarize de l'index est activé, ce qui n'est pas le cas par défaut, à chaque fois que l'autovacuum est exécuté dans cette base, le résumé surviendra pour tous les intervalles de blocs non résumés qui ont été remplis, que la table elle-même soit traitée par l'autovacuum ou pas ; voir ci-dessous.

Dernièrement, les fonctions suivantes peuvent être utilisées :

brin_summarize_new_values(regclass) qui résume tous les blocs sans résumé ;
brin_summarize_range(regclass, bigint) qui résume seulement l'intervalle contenant le bloc donné s'il n'est pas résumé.

Quand le résumé automatique est activé, une requête est envoyée à l'autovacuum pour exécuter un résumé cible pour un intervalle de bloc quand une insertion est détecté pour le premier élément du premier bloc du prochain intervalle de bloc, opération à réaliser la prochaine fois qu'un autovacuum worker finit son exécution dans la même base. Si la queue des demandes est remplie, la demande n'est pas enregistrée et un message est enregistré dans les traces du serveur :

 LOG:  request for BRIN range summarization for index "brin_wi_idx" page 128 was not recorded
    

Quand cela arrive, l'intervalle restera non résumé jusqu'à la prochaine exécution d'un vacuum standard sur la table ou jusqu'à ce qu'une des fonctions mentionnées ci-dessus soit appelée.

Inversement, un intervalle peut se voir supprimer son résumé avec la fonction brin_desummarize_range(regclass, bigint), qui est utile quand l'enregistrement de l'index n'est plus une très bonne représentation car les valeurs existantes ont changées. Voir Section 9.27.8 pour les détails.