BRIN signifie Block Range Index, soit index par intervalles de bloc. BRIN est concu pour gérer de grosses tables dont certaines ont des colonnes ayant une corrélation naturelle avec leur stockage physique. Un intervalle de bloc est un groupe de pages physiquement adjacentes 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.
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 ne crée pas automatiquement
un résumé. Ces lignes restent non catégorisées jusqu'à ce qu'un processus
soit lancé pour le faire, créant alors les résumés initiaux.
Ce processus peut être appelé manuellement en exécutant la fonction
brin_summarize_range(regclass, bigint)
ou la fonction
brin_summarize_new_values(regclass)
;
automatiquement lorsque VACUUM
va inspecter la
table ;
ou par un résumé automatique effectué par autovacuum, au fur et à mesure que
des insertions sont effectuées. (Ce dernier déclencheur est désactivé par
défaut, et peut être activé avec le paramètre
autosummarize
.) Inversement, le résumé d'un intervalle peut être
supprimé en utilisant la fonction brin_desummarize_range(regclass,
bigint)
, ce qui peut être utile quand la ligne de l'index n'est
plue une bonne représentation du fait des changements des valeurs
existantes.
Quand le résumé automatique est activé, chaque fois qu'un intervalle de page est rempli, une requête est envoyée à autovacuum pour qu'il exécute un résumé ciblé pour cet intervalle, opération à exécuter à la fin du travail du prochain worker sur la même base de données. Si la queue des demandes est remplie, la demande n'est pas enregistré 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 sera résumé avec la méthode habituelle lors du prochain VACUUM standard de la table.