Skip to content

Indexation SQL expliquée

Une antisèche sur les types d'index SQL, les motifs de conception et la maintenance.

Les index échangent stockage et vitesse d'écriture contre de la vitesse de lecture. Choisissez la structure, délimitez les lignes, et maîtrisez le ballonnement.

Tableau de référence · 31 entrées
31 of 31 rows
Types d'index
Arbre équilibré pour les égalités, les plages et les scans triés. Valeur par défaut dans la plupart des bases.Utilisez pour =, <, >, BETWEEN, ORDER BY. Évitez pour la recherche plein texte.
Index dont le niveau de feuilles est la table elle-même. Les lignes sont stockées dans l'ordre de la clé. Un seul par table.InnoDB s'organise autour de la clé primaire. Les tables SQL Server sans index clusterisé sont des heaps.
Structure séparée contenant les clés plus un pointeur vers la table de base. Plusieurs par table.Sur un heap il stocke un ID de ligne. Sur une table clusterisée il stocke la clé de clustering.
Table de hachage pour les recherches par égalité uniquement. Correspondance exacte en temps constant.À utiliser seulement pour les opérations = ; les plages et le tri exigent un B-tree. Le hash memory-optimized de SQL Server demande un bucket count proche du nombre de lignes.
Generalized Inverted Index. Associe des valeurs à des lignes. Conçu pour les tableaux et le plein texte.Utilisez pour jsonb, les tableaux, tsvector, la recherche par trigramme. Plus lent à construire qu'un B-tree.
Generalized Search Tree. Extensible pour les types non scalaires et les requêtes de chevauchement.Utilisez pour les plages géométriques, kNN, les contraintes d'exclusion. pg_trgm accélère LIKE.
GiST à partitionnement spatial. Découpe les données en régions sans chevauchement via des arbres radix ou quad.Utilisez pour les points, les préfixes IP et la correspondance par préfixe. Pas pour le chevauchement ; utilisez GiST.
Block Range Index. Stocke min/max par plage de blocs. Empreinte minuscule.À utiliser sur de grandes tables physiquement triées. Bon marché à construire, faible sélectivité.
Index stocké en segments de colonnes au lieu de lignes. Forte compression, exécution par lots.Utilisez pour les scans analytiques sur beaucoup de lignes et peu de colonnes. Les lectures ligne à ligne sont lentes.
Index inversé de mots dédié dans MySQL et SQL Server. Construit par colonne texte.Utilisez MATCH AGAINST ou CONTAINS. Le plein texte de Postgres utilise GIN sur tsvector à la place.
Index Oracle stockant un bitmap par valeur distincte. Chaque bit marque une ligne.À utiliser sur des colonnes de faible cardinalité dans des entrepôts à lecture intensive. Les écritures concurrentes se sérialisent par bitmap.
Colonne d'index déclarée DESC. Les clés de cette colonne sont stockées en ordre inverse.Nécessaire pour les tris mixtes comme (a ASC, b DESC). Les tris DESC simples peuvent aussi lire un index normal à l'envers.
Index de MySQL 8 ignoré par l'optimiseur. Toujours maintenu à chaque écriture.Masquez un index avant de le supprimer pour mesurer l'impact. Rendez-le visible à nouveau sans reconstruction.
Conception
Index multi-colonnes. Les colonnes de tête doivent suivre l'ordre des filtres de la requête.Ordonnez par égalité d'abord, puis par plage. Deux index simples ne remplacent pas un composite.
Index sur un prédicat WHERE. SQL Server l'appelle filtered index. Ne couvre que les lignes correspondantes.Indexez seulement les lignes active='t'. Divise par deux la taille et le coût d'écriture.
B-tree avec des colonnes non-clé ajoutées. Les scans index-only évitent les allers-retours au heap.Ajoutez les colonnes souvent lues via INCLUDE. Garde l'index triable.
Index qui interdit les valeurs dupliquées. Rejette les inserts en collision.Utilisez pour les clés naturelles et les contraintes un-à-un. UNIQUE NULL autorise plusieurs NULL.
Index construit sur une fonction des colonnes plutôt que sur les colonnes elles-mêmes.Indexez lower(email) ou date_trunc('day', created_at). La requête doit répéter l'expression exacte.
Classe d'opérateurs. Définit comment un index compare et stocke le type d'une colonne.Réglez varchar_pattern_ops pour LIKE 'abc%' sans repli de casse. Les valeurs par défaut conviennent à l'égalité et aux plages.
Plan qui répond à une requête depuis les seules pages de l'index. Le heap n'est jamais lu.Exige chaque colonne lue dans l'index ou la liste INCLUDE. Le vacuum maintient la visibility map à jour.
Les colonnes de clé étrangère n'obtiennent aucun index automatique sur la table référençante.Indexez chaque colonne de FK par laquelle vous joignez ou supprimez. Les suppressions en cascade scannent la table enfant sans index.
Maintenance
Inspecteur de plan. Montre les scans séquentiels, les choix d'index, les estimations de coût.Utilisez EXPLAIN (ANALYZE, BUFFERS). Un Seq Scan sur une table de 10M lignes signale un index manquant.
Échantillonne les colonnes de la table pour construire les statistiques du planificateur. Les histogrammes guident le choix d'index.Lancez après les chargements massifs. Des stats périmées provoquent des seq scans sur des colonnes indexées.
Chaque index ajoute un coût d'écriture. Inserts, updates et deletes paient pour chaque index.Supprimez les index inutilisés. Suivez l'usage dans pg_stat_user_indexes.
Vue Postgres de l'usage par index. Compte les scans et tuples lus depuis la dernière réinitialisation.Filtrez sur idx_scan = 0 pour trouver les index inutilisés. Réinitialisez les compteurs avec pg_stat_reset().
Construit un index sans bloquer lectures ni écritures. Nécessite deux scans de table.Impossible dans une transaction. Une construction échouée laisse un index INVALID à supprimer.
Supprime un index et libère son stockage. Prend un verrou exclusif par défaut.Utilisez DROP INDEX CONCURRENTLY sur les tables chargées. Vérifiez les statistiques d'usage avant de retirer.
Reconstruit un index gonflé. Récupère l'espace des tuples morts.Utilisez REINDEX CONCURRENTLY en production. Sans lui, les verrous bloquent les écritures.
Tuples morts et trous de pages qui s'accumulent dans les tables MVCC et leurs index.Mesurez avec pgstattuple. Vacuum souvent ; REINDEX quand l'espace mort domine.
Pourcentage d'une page rempli à l'écriture. L'espace libre absorbe les mises à jour futures.Baissez-le à 70-90 sur les tables à mises à jour fréquentes. Les pages pleines forcent des page splits.
Réécrit la table physiquement ordonnée selon un index. Opération ponctuelle.Se combine avec BRIN pour des blocs triés. L'ordre n'est pas maintenu lors des écritures suivantes.