Quelles colonnes font généralement de bons index?

98

En guise de suivi de " Que sont les index et comment puis-je les utiliser pour optimiser les requêtes dans ma base de données? ", Où j'essaie d'en savoir plus sur les index, quelles colonnes sont de bons candidats d'index? Spécifiquement pour une base de données MS SQL?

Après quelques recherches sur Google, tout ce que j'ai lu suggère que les colonnes qui augmentent généralement et sont uniques constituent un bon index (des choses comme l'auto_increment de MySQL), je comprends cela, mais j'utilise MS SQL et j'utilise des GUID pour les clés primaires, il semble donc que les index ne profiteraient pas aux colonnes GUID ...

mmattax
la source
Que diriez-vous d'un "livre de recettes": mysql.rjweb.org/doc.php/index_cookbook_mysql
Rick James

Réponses:

110

Les index peuvent jouer un rôle important dans l'optimisation des requêtes et la recherche rapide des résultats à partir des tables. Il est donc très important de sélectionner les colonnes à indexer. Il existe deux endroits principaux où nous pouvons envisager l'indexation: les colonnes référencées dans la clause WHERE et les colonnes utilisées dans les clauses JOIN. En bref, ces colonnes doivent être indexées par rapport auxquelles vous devez rechercher des enregistrements particuliers. Supposons que nous ayons une table nommée acheteurs où la requête SELECT utilise des index comme ci-dessous:

SELECT
 buyer_id /* no need to index */
FROM buyers
WHERE first_name='Tariq' /* consider to use index */
AND last_name='Iqbal'   /* consider to use index */

Puisque "acheteur_id" est référencé dans la partie SELECT, MySQL ne l'utilisera pas pour limiter les lignes choisies. Par conséquent, il n'est pas nécessaire de l'indexer. Ci-dessous est un autre exemple peu différent de celui ci-dessus:

SELECT
 buyers.buyer_id, /* no need to index */
 country.name    /* no need to index */
FROM buyers LEFT JOIN country
ON buyers.country_id=country.country_id /* consider to use index */
WHERE
 first_name='Tariq' /* consider to use index */
AND
 last_name='Iqbal' /* consider to use index */

Selon les requêtes ci-dessus first_name, les colonnes last_name peuvent être indexées car elles se trouvent dans la clause WHERE. Un champ supplémentaire, country_id de la table country, peut également être pris en compte pour l'indexation car il se trouve dans une clause JOIN. L'indexation peut donc être envisagée sur chaque champ de la clause WHERE ou d'une clause JOIN.

La liste suivante propose également quelques conseils que vous devez toujours garder à l'esprit lorsque vous avez l'intention de créer des index dans vos tables:

  • Indexez uniquement les colonnes requises dans les clauses WHERE et ORDER BY. L'indexation des colonnes en abondance entraînera certains inconvénients.
  • Essayez de profiter de la fonctionnalité "préfixe d'index" ou "index multi-colonnes" de MySQL. Si vous créez un index tel que INDEX (prénom, nom), ne créez pas INDEX (prénom). Cependant, "préfixe d'index" ou "index multi-colonnes" n'est pas recommandé dans tous les cas de recherche.
  • Utilisez l'attribut NOT NULL pour les colonnes dans lesquelles vous envisagez l'indexation, afin que les valeurs NULL ne soient jamais stockées.
  • Utilisez l'option --log-long-format pour consigner les requêtes qui n'utilisent pas d'index. De cette manière, vous pouvez examiner ce fichier journal et ajuster vos requêtes en conséquence.
  • L'instruction EXPLAIN vous aide à révéler comment MySQL exécutera une requête. Il montre comment et dans quel ordre les tables sont jointes. Cela peut être très utile pour déterminer comment écrire des requêtes optimisées et si les colonnes doivent être indexées.

Mise à jour (23 février 15):

Tout index (bon / mauvais) augmente le temps d'insertion et de mise à jour.

En fonction de vos index (nombre d'index et type), le résultat est recherché. Si votre temps de recherche augmente à cause de l'index, c'est un mauvais index.

Probablement dans n'importe quel livre, "Page d'index" peut avoir une page de début de chapitre, un numéro de page de sujet commence, ainsi qu'une page de sous-sujet. Certaines clarifications dans la page d'index sont utiles, mais un index plus détaillé peut vous dérouter ou vous effrayer. Les index ont également de la mémoire.

La sélection d'index doit être judicieuse. Gardez à l'esprit que toutes les colonnes ne nécessitent pas d'index.

Somnath Muluk
la source
Merci Somnath, cela implique-t-il que les index ne doivent être créés que pour les colonnes que nous prévoyons d'utiliser WHERE, JOINSou HAVING?
Muhammad Babar
3
Oui, utilisez des index pour les colonnes où vous prévoyez d'utiliser WHERE, JOINS ou HAVING. Mais gardez également à l'esprit que toutes les colonnes de condition ne nécessitent pas d'index. Parfois, lorsque la colonne de condition n'est utilisée qu'une seule fois, elle n'a peut-être pas besoin d'index, tandis qu'une autre colonne de condition est utilisée dans de nombreuses requêtes, préférez donc plus pour l'indexation à cette colonne.
Somnath Muluk
1
La réponse gagnerait à mettre «les colonnes référencées dans la clause WHERE et les colonnes utilisées dans les clauses JOIN» dans une section TL; DR.
jpmc26
Donc, vous dites que si dans ma WHEREclause je vérifie la valeur d'un champ où sa colonne ne peut prendre que deux valeurs, alors je devrais indexer cette colonne binaire? Cela semble faux.
AjaxLeung
@AjaxLeung: Souvenez-vous de la maxime de Knuth "L'optimisation prématurée est la racine de tout mal.". Vous pouvez créer un index sur des colonnes binaires, mais cela devrait dépendre de quel coût (comme l'insertion, les heures de mise à jour). Si votre logique métier dépend souvent de ce commutateur binaire, la colonne binaire peut être requise pour avoir un index.
Somnath Muluk
20

Certaines personnes ont répondu à une question similaire ici: comment savoir ce qu'est un bon index?

Fondamentalement, cela dépend vraiment de la façon dont vous interrogerez vos données. Vous voulez un index qui identifie rapidement un petit sous-ensemble de votre ensemble de données qui est pertinent pour une requête. Si vous n'interrogez jamais par horodatage, vous n'avez pas besoin d'un index dessus, même s'il est généralement unique. Si tout ce que vous faites est d'obtenir des événements qui se sont produits dans une certaine plage de dates, vous en voulez certainement un. Dans la plupart des cas, un index sur le sexe est inutile - mais si vous ne faites que obtenir des statistiques sur tous les hommes, et séparément, sur toutes les femmes, cela vaut peut-être la peine d'en créer un. Déterminez quels seront vos modèles de requête et accédez à quel paramètre réduit le plus l'espace de recherche, et c'est votre meilleur index.

Considérez également le type d'index que vous créez - les arbres B sont bons pour la plupart des choses et permettent les requêtes de plage, mais les index de hachage vous amènent directement au point (mais n'autorisent pas les plages). D'autres types d'index ont d'autres avantages et inconvénients.

Bonne chance!

SquareCog
la source
9

Tout dépend des requêtes que vous vous attendez à poser sur les tables. Si vous demandez toutes les lignes avec une certaine valeur pour la colonne X, vous devrez effectuer une analyse complète de la table si un index ne peut pas être utilisé.

Les index seront utiles si:

  • La ou les colonnes ont un haut degré d'unicité
  • Vous devez souvent rechercher une certaine valeur ou une plage de valeurs pour la colonne.

Ils ne seront pas utiles si:

  • Vous sélectionnez un grand% (> 10-20%) des lignes du tableau
  • L'utilisation de l'espace supplémentaire est un problème
  • Vous souhaitez optimiser les performances d'insertion. Chaque index sur une table réduit les performances d'insertion et de mise à jour, car ils doivent être mis à jour chaque fois que les données changent.

Les colonnes de clé primaire sont généralement idéales pour l'indexation car elles sont uniques et souvent utilisées pour rechercher des lignes.

Plasmer
la source
les recherches de chaîne où la valeur peut être n'importe où dans la chaîne peuvent empêcher l'utilisation de ces index dans ce cas.
Arthur Thomas
5

En général (je n'utilise pas mssql, je ne peux donc pas commenter spécifiquement), les clés primaires font de bons index. Ils sont uniques et doivent avoir une valeur spécifiée. (De plus, les clés primaires font de si bons index qu'ils ont normalement un index créé automatiquement.)

Un index est en fait une copie de la colonne qui a été triée pour permettre la recherche binaire (ce qui est beaucoup plus rapide que la recherche linéaire). Les systèmes de base de données peuvent utiliser diverses astuces pour accélérer encore plus la recherche, en particulier si les données sont plus complexes qu'un simple nombre.

Ma suggestion serait de ne pas utiliser d'index au départ et de profiler vos requêtes. Si une requête particulière (comme la recherche de personnes par nom de famille, par exemple) est exécutée très souvent, essayez à nouveau de créer un index sur les attributs pertinents et le profil. S'il y a une accélération notable sur les requêtes et un ralentissement négligeable sur les insertions et les mises à jour, conservez l'index.

(Excusez-moi si je répète des choses mentionnées dans votre autre question, je ne les avais pas rencontrées auparavant.)

Zooba
la source
5

Toute colonne qui sera régulièrement utilisée pour extraire des données de la table doit être indexée.

Cela comprend: les clés étrangères -

select * from tblOrder where status_id=:v_outstanding

champs descriptifs -

select * from tblCust where Surname like "O'Brian%"

Les colonnes n'ont pas besoin d'être uniques. En fait, vous pouvez obtenir de très bonnes performances à partir d'un index binaire lors de la recherche d'exceptions.

select * from tblOrder where paidYN='N'
pappes
la source
Votre mention explicite des clés étrangères a vraiment clarifié les choses pour moi en ce qui concerne les jointures.
pfabri
3

Cela dépend vraiment de vos requêtes. Par exemple, si vous n'écrivez quasiment que dans une table, il est préférable de ne pas avoir d'index, ils ralentissent simplement les écritures et ne s'utilisent jamais. Toute colonne que vous utilisez pour joindre une autre table est un bon candidat pour un index.

Consultez également la fonctionnalité d'index manquant. Il surveille les requêtes réelles utilisées sur votre base de données et peut vous dire quels index auraient amélioré les performances.

Jwanagel
la source
3

Une colonne GUID n'est pas le meilleur candidat pour l'indexation. Les index sont les mieux adaptés aux colonnes avec un type de données qui peut recevoir un ordre significatif, c'est-à-dire triées (entier, date, etc.).

Peu importe si les données d'une colonne augmentent généralement. Si vous créez un index sur la colonne, l'index créera sa propre structure de données qui référencera simplement les éléments réels de votre table sans se soucier de l'ordre de stockage (un index non clusterisé). Ensuite, par exemple, une recherche binaire peut être effectuée sur votre structure de données d'index pour fournir une récupération rapide.

Il est également possible de créer un «index clusterisé» qui réorganisera physiquement vos données. Cependant, vous ne pouvez en avoir qu'un par table, alors que vous pouvez avoir plusieurs index non clusterisés.

Cendre
la source
Eh bien, ce n'est pas totalement exact de cette façon. Vous pouvez facilement créer un index standard non clusterisé sur une colonne GUID - pourquoi pas? Le GUID a un gros inconvénient si vous l'utilisez comme clé de clustering (par exemple pour le CLUSTERED INDEX) - alors c'est un désastre à utiliser.
marc_s
1

L'ancienne règle d'or était les colonnes qui sont beaucoup utilisées dans les clauses WHERE, ORDER BY et GROUP BY, ou celles qui semblaient être utilisées fréquemment dans les jointures. Gardez à l'esprit que je fais référence aux index, PAS à la clé primaire

Ne pas donner une réponse `` vanilla-ish '', mais cela dépend vraiment de la façon dont vous accédez aux données

ridicule
la source
1

Votre clé primaire doit toujours être un index. (Je serais surpris si ce n'était pas automatiquement indexé par MS SQL, en fait.) Vous devriez également indexer les colonnes vous SELECTou ORDERpar fréquemment; leur objectif est à la fois la recherche rapide d'une valeur unique et un tri plus rapide.

Le seul vrai danger dans l'indexation de toonombreuses colonnes est de ralentir les modifications apportées aux lignes dans les grandes tables, car les index doivent tous être mis à jour également. Si vous ne savez vraiment pas quoi indexer, chronométrez simplement vos requêtes les plus lentes, regardez quelles colonnes sont utilisées le plus souvent et indexez-les. Ensuite, voyez à quel point ils sont plus rapides.

Évoli
la source
1

Les types de données numériques classés par ordre croissant ou décroissant sont de bons index pour plusieurs raisons. Premièrement, les nombres sont généralement plus rapides à évaluer que les chaînes (varchar, char, nvarchar, etc.). Deuxièmement, si vos valeurs ne sont pas ordonnées, les lignes et / ou les pages devront peut-être être mélangées pour mettre à jour votre index. C'est des frais généraux supplémentaires.

Si vous utilisez SQL Server 2005 et que vous utilisez des identificateurs uniques (guids) et que vous n'avez PAS besoin qu'ils soient de nature aléatoire, consultez le type d'identificateur unique séquentiel.

Enfin, si vous parlez d'index clusterisés, vous parlez du type de données physiques. Si vous avez une chaîne comme index cluster, cela peut devenir moche.

Ian Suttle
la source
0

Cela devrait être encore plus rapide si vous utilisez un GUID. Supposons que vous ayez les dossiers

  1. 100
  2. 200
  3. 3000
  4. ....

Si vous avez un index (recherche binaire, vous pouvez trouver l'emplacement physique de l'enregistrement que vous recherchez dans le temps O (lg n), au lieu de chercher séquentiellement le temps O (n). C'est parce que vous ne savez pas quels enregistrements vous avez dans votre table.

Milhous
la source
0

Le meilleur index dépend du contenu de la table et de ce que vous essayez d'accomplir.

Prenons un exemple Une base de données de membres avec une clé primaire du numéro de sécurité sociale des membres. Nous choisissons le SS parce que l'application priamry fait référence à l'individu de cette manière, mais vous souhaitez également créer une fonction de recherche qui utilisera le nom et le prénom des membres. Je suggérerais alors de créer un index sur ces deux champs.

Vous devez d'abord savoir quelles données vous allez interroger, puis déterminer les données dont vous avez besoin indexées.

Joseph
la source