Deux index à une seule colonne vs un index à deux colonnes dans MySQL?

114

Je suis confronté à ce qui suit et je ne suis pas sûr de la meilleure pratique.

Considérez le tableau suivant (qui deviendra grand):

id PK | giver_id FK | destinataire_id FK | Date

J'utilise InnoDB et d'après ce que je comprends, il crée automatiquement des index pour les deux colonnes de clé étrangère. Cependant, je vais également faire beaucoup de requêtes dans lesquelles je dois faire correspondre une combinaison particulière de:

SELECT...WHERE giver_id = x AND recipient_id = t.

Chacune de ces combinaisons sera unique dans le tableau.

Y a-t-il un avantage à ajouter un index à deux colonnes sur ces colonnes, ou les deux index individuels seraient-ils en théorie suffisants / identiques?

À M
la source
1
Si la combinaison des deux colonnes est unique, vous pouvez créer un index à deux colonnes avec une fonctionnalité unique qui non seulement augmentera la vitesse de votre requête, mais ajoutera également de la cohérence à votre table.
sguven
"MySQL peut utiliser des index à plusieurs colonnes pour les requêtes qui testent toutes les colonnes de l'index, ou des requêtes qui testent uniquement la première colonne, les deux premières colonnes, les trois premières colonnes, etc. Si vous spécifiez les colonnes à droite dans la définition d'index, un seul index composite peut accélérer plusieurs types de requêtes sur la même table. " - Index à plusieurs colonnes
AlikElzin-kilaka
Pour extrapoler sur @ user1585784; Si la combinaison des deux colonnes est unique, je pense qu'il faut utiliser une clé unique pour elles. En fait, si l'on veut imposer l'unicité au niveau de la base de données, une clé unique est le moyen le plus simple d'aller ...
Erk

Réponses:

133

Si vous avez deux index à une seule colonne, un seul d'entre eux sera utilisé dans votre exemple.

Si vous avez un index avec deux colonnes, la requête peut être plus rapide (vous devez mesurer). Un index à deux colonnes peut également être utilisé comme un index de colonne unique, mais uniquement pour la colonne répertoriée en premier.

Parfois, il peut être utile d'avoir un index sur (A, B) et un autre index sur (B). Cela accélère les requêtes utilisant l'une ou les deux colonnes, mais utilise bien sûr également plus d'espace disque.

Lors du choix des index, vous devez également tenir compte de l'effet sur l'insertion, la suppression et la mise à jour. Plus d'index = mises à jour plus lentes.

Mark Byers
la source
1
"MySQL peut utiliser des index à plusieurs colonnes pour les requêtes qui testent toutes les colonnes de l'index, ou des requêtes qui testent uniquement la première colonne, les deux premières colonnes, les trois premières colonnes, etc. Si vous spécifiez les colonnes à droite dans la définition d'index, un seul index composite peut accélérer plusieurs types de requêtes sur la même table. " - Index à colonnes multiples
AlikElzin-kilaka
33

Un index de couverture comme:

ALTER TABLE your_table ADD INDEX (giver_id, recipient_id);

... signifierait que l'index pourrait être utilisé si une requête référencée giver_idou une combinaison de giver_idet recipient_id. Gardez à l'esprit que les critères d'index sont basés à l'extrême gauche - une requête faisant référence uniquement ne recipient_idpourrait pas utiliser l'index de couverture dans la déclaration que j'ai fournie.

De plus, MySQL ne peut utiliser qu'un seul index par SELECT, donc un index de couverture serait le meilleur moyen d'optimiser vos requêtes.

Poneys OMG
la source
10
MySQL can only use one index per SELECTce n'est plus vrai, ce serait bien si vous éditiez votre réponse pour qu'elle soit mise à jour.
Davor du
Pourriez-vous expliquer pourquoi l'index de couverture ne pourrait pas être utilisé par recipient_id?
Ivo Pereira
2
@IvoPereira Les index multi-colonnes dans MySQL vous permettent d'utiliser tous les champs de l'index de gauche à droite. Par exemple, si vous avez un INDEX (col1, col2, col3, col4)alors l'index sera appliqué pour les recherches avec une WHEREclause comme col1 = 'A'ou col1 = 'A' AND col2 = 'B'ou col1 = 'A' AND col2 ='B' AND col3 = 'C' AND col4 = 'D', mais cet index particulier ne sera pas utilisé pour quelque chose comme WHERE col2 = 'B'ou WHERE col3 = 'C' AND col4 = 'D'parce que les champs de recherche ne sont pas les plus laissés dans la définition d'index. Vous devrez ajouter des index supplémentaires pour couvrir ces champs.
Slicktrick
"un index par SELECT" , est-ce toujours vrai pour mariadb 10.1?
oldboy
1
@Anthony: Non, voyez le commentaire de Davor ci-dessus.
kapad
4

Si l'un des index de clé étrangère est déjà très sélectif, le moteur de base de données doit l'utiliser pour la requête que vous avez spécifiée. La plupart des moteurs de base de données utilisent une sorte d'heuristique pour pouvoir choisir l'index optimal dans cette situation. Si aucun des deux index n'est très sélectif en soi, il est probablement judicieux d'ajouter l'index construit sur les deux clés, car vous dites que vous utiliserez beaucoup ce type de requête.

Une autre chose à considérer est de savoir si vous pouvez éliminer le champ PK de cette table et définir l'index de clé primaire sur les champs giver_idet recipient_id. Vous avez dit que la combinaison est unique, donc cela fonctionnerait probablement (étant donné de nombreuses autres conditions auxquelles vous seul pouvez répondre). En règle générale, cependant, je pense que la complexité supplémentaire qui ajoute ne vaut pas la peine.

Mark Wilkins
la source
Merci Mark, une des touches est en effet très sélective donc ça devrait aller. J'ai choisi de garder les deux indices (automatiques) en place et de voir comment ils fonctionnent au fil du temps. J'ai aussi pensé à une clé primaire combinée donneur: destinataire, mais comme chaque champ doit également être recherché individuellement, cela ajouterait simplement une surcharge php. En outre, la nouvelle clé serait une chaîne (plus longue) au lieu d'un entier (plus court).
Tom
2

Une autre chose à considérer est que les caractéristiques de performance des deux approches seront basées sur la taille et la cardinalité de l'ensemble de données. Vous constaterez peut-être que l'index à 2 colonnes ne devient plus performant qu'à un certain seuil de taille de jeu de données, ou exactement le contraire. Rien ne peut remplacer les mesures de performances pour votre scénario exact.

Andrew
la source
pourriez-vous s'il vous plaît un lien vers une documentation à ce sujet. Merci.
kapad