web-dev-qa-db-fra.com

Inconvénient des performances de la clé primaire composite dans MySQL

Nous avons une table avec une clé primaire composite composée de trois champs (et c'est dans MySQL 5.1). Il y a près de 200 insertions et 200 sélections par seconde sur cette table, et la taille de la table est d'environ 1 million de lignes et elle augmente.

Ma question est: la "clé primaire composite" diminue-t-elle les performances des insertions et sélections sur cette table?

Dois-je utiliser un simple champ ID INT à augmentation automatique au lieu d'une clé primaire composite? (Je pense que la réponse est très liée à la façon dont MySQL gère les index sur plusieurs colonnes)

43
Ahmad

INSERT et UPDATE les performances varient peu: elles seront quasiment les mêmes pour (INT) et (INT, INT) clés.

SELECT performances du composite PRIMARY KEY dépend de nombreux facteurs.

Si votre table est InnoDB, alors la table est implicitement groupée sur le PRIMARY KEY valeur.

Cela signifie que la recherche des deux valeurs sera plus rapide si les deux valeurs comprennent la clé: aucune recherche de clé supplémentaire ne sera requise.

En supposant que votre requête ressemble à ceci:

SELECT  *
FROM    mytable
WHERE   col1 = @value1
        AND col2 = @value2

et la disposition du tableau est la suivante:

CREATE TABLE mytable (
        col1 INT NOT NULL,
        col2 INT NOT NULL,
        data VARCHAR(200) NOT NULL,
        PRIMARY KEY pk_mytable (col1, col2)
) ENGINE=InnoDB

, le moteur devra simplement rechercher la valeur de clé exacte dans la table elle-même.

Si vous utilisez un champ d'auto-incrémentation comme faux identifiant:

CREATE TABLE mytable (
        id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
        col1 INT NOT NULL,
        col2 INT NOT NULL,
        data VARCHAR(200) NOT NULL,
        UNIQUE KEY ix_mytable_col1_col2 (col1, col2)
) ENGINE=InnoDB

, le moteur devra d'abord rechercher les valeurs de (col1, col2) dans l'index ix_mytable_col1_col2, récupérez le pointeur de ligne dans l'index (la valeur de id) et effectuez une autre recherche par id dans la table elle-même.

Cependant, pour les tables MyISAM, cela ne fait aucune différence, car les tables MyISAM sont organisées en tas et le pointeur de ligne n'est qu'un décalage de fichier.

Dans les deux cas, un même index sera créé (pour PRIMARY KEY ou pour UNIQUE KEY) et sera utilisé de la même manière.

55
Quassnoi

S'il s'agit d'InnoDB, la clé primaire composite sera incluse dans chaque entrée de chacun des index secondaires.

Cela signifie que

  • Vos index secondaires prendront autant d'espace que ces colonnes + toutes les colonnes de la clé primaire
  • Vous pouvez utiliser un index secondaire comme index de couverture si toutes les colonnes requises sont contenues dans l'index secondaire + pk

Ce sont bien sûr respectivement un inconvénient et un avantage.

Les clés primaires composites ne sont pas nécessairement mauvaises, parfois elles peuvent être très utiles car InnoDB les regroupe - ce qui signifie que les analyses de plage (liées au disque) sur le PK peuvent être satisfaites en utilisant beaucoup moins IO opérations que serait requis sur un index non clusterisé.

Bien sûr, si vous avez des clés étrangères dans d'autres tables, elles sont plus larges et doivent inclure la clé entière de votre table principale.

Mais je dirais dans l'ensemble, non. Avoir une clé primaire composite ne pose PAS de problème en soi. Avoir une "grande" clé primaire (par exemple, de gros varchars) peut cependant faire l'affaire, si cela l'emporte sur les avantages du clustering et pouvoir utiliser des index de couverture.

22
MarkR
  1. Avoir cette clé primaire composite ralentit SELECTs un tout petit peu, bien que l'effet soit à peu près négligeable et ne vaut pas la peine de s'inquiéter.
  2. L'indexation de ces colonnes pas du tout ralentit vos INSERTs, et vous en faites certainement INSERTs pour vous en inquiéter. C'est beaucoup plus une préoccupation s'il s'agit d'une table MyISAM, où un INSERT verrouille la table, que s'il s'agit d'une table InnoDB. Si, en utilisant la clé primaire auto_increment, vous pouviez laisser ces colonnes non indexées, vous bénéficieriez de la modification. Cependant, si vous devez toujours garder ces trois colonnes indexées (par exemple, si vous devez appliquer l'unicité à leur combinaison), cela ne fera rien pour vous en termes de performances.
3
chaos