@Pierre 303 l'a déjà dit, mais je le redis. UTILISEZ les index sur les combinaisons de colonnes. Un index combiné activé (a, b)
n'est que légèrement plus lent pour les requêtes activées a
qu'un index a
seul et est considérablement meilleur si votre requête combine les deux colonnes. Certaines bases de données peuvent joindre des index sur a
et b
avant d'atteindre la table, mais ce n'est pas aussi bon que d'avoir un index combiné. Lorsque vous créez un index combiné, vous devez placer la colonne la plus susceptible d'être recherchée en premier dans l'index combiné.
Si votre base de données prend en charge, DO mettre les index sur les fonctions qui apparaissent dans les requêtes plutôt que des colonnes. (Si vous appelez une fonction sur une colonne, les index de cette colonne sont inutiles.)
Si vous utilisez une base de données avec de vraies tables temporaires que vous pouvez créer et détruire à la volée (par exemple , PostgreSQL, MySQL, mais pas Oracle), puis NE créer des index sur les tables temporaires.
Si vous utilisez une base de données qui permet (par exemple Oracle), DO verrouillage dans les bons plans de requête. Les optimiseurs de requête au fil du temps modifieront les plans de requête. Ils améliorent généralement le plan. Mais parfois, ils aggravent considérablement les choses. Vous ne remarquerez généralement pas vraiment les améliorations du plan - la requête n'était pas un goulot d'étranglement. Mais un seul mauvais plan peut détruire un site très fréquenté.
NE PAS avoir d'index sur les tables sur lesquelles vous êtes sur le point d'effectuer un chargement de données important. Il est beaucoup, beaucoup plus rapide de supprimer des index, de charger les données, puis de reconstruire les index que de les maintenir lors du chargement de la table.
N'UTILISEZ PAS les index sur les requêtes qui doivent accéder à plus d'une petite fraction d'une grande table. (La taille dépend du matériel. 5% est une règle empirique décente.) Par exemple, si vous avez des données avec des noms et un sexe, les noms sont un bon candidat pour l'indexation car tout nom donné représente une petite fraction du nombre total de lignes. Il ne serait pas utile d'indexer le sexe, car vous devrez toujours accéder à 50% des lignes. Vous voulez vraiment utiliser une analyse complète de la table à la place. La raison en est que les index finissent par accéder à un fichier volumineux de manière aléatoire, ce qui vous oblige à rechercher des disques. Les recherches de disque sont lentes. À titre d'exemple, j'ai récemment réussi à accélérer une requête d'une heure qui ressemblait à:
SELECT small_table.id, SUM(big_table.some_value)
FROM small_table
JOIN big_table
ON big_table.small_table_id = small_table.id
GROUP BY small_table.id
à moins de 3 minutes en le réécrivant comme suit:
SELECT small_table.id, big_table_summary.summed_value
FROM small_table
JOIN (
SELECT small_table_id, SUM(some_value) as summed_value
FROM big_table
GROUP BY small_table_id
) big_table_summary
ON big_table_summary.small_table_id = small_table.id
ce qui a forcé la base de données à comprendre qu'elle ne devrait pas essayer d'utiliser l'index tentant sur big_table.small_table_id
. (Une bonne base de données, comme Oracle, devrait le comprendre par elle-même. Cette requête s'exécutait sur MySQL.)
Mise à jour: Voici une explication du point de recherche de disque que j'ai fait. Un index donne une recherche rapide pour dire où se trouvent les données dans le tableau. C'est généralement une victoire puisque vous ne regarderez que les données dont vous avez besoin. Mais pas toujours, surtout si vous finirez par consulter un grand nombre de données. Les disques diffusent bien les données, mais ralentissent les recherches. Une recherche aléatoire de données sur disque prend 1 / 200e de seconde. La version lente de la requête a fini par en faire quelque chose comme 600 000 et a pris près d'une heure. (Il a fait plus de recherches que cela, mais la mise en cache a attrapé certaines d'entre elles.) En revanche, la version rapide savait qu'elle devait tout lire et diffuser des données à quelque chose comme 70 Mo / seconde. Il a traversé une table de 11 Go en moins de 3 minutes.