2010-08-20 18 views
2

j'ai une base de données créée avec un outil graphique et je l'ai remarqué ce qui semble être une utilisation non uniforme de KEY (alias INDEX) Définitions:index sur des clés primaires et étrangères

CREATE TABLE `foo_bar` (
    `foo_id` int(10) unsigned NOT NULL, 
    `bar_id` int(10) unsigned NOT NULL, 
    PRIMARY KEY (`foo_id`, `bar_id`), 
    KEY `foo_bar_fk2` (`bar_id`), -- <== ??? 
    CONSTRAINT `foo_bar_fk1` FOREIGN KEY (`foo_id`) REFERENCES `foo` (`foo_id`) ON DELETE CASCADE ON UPDATE CASCADE, 
    CONSTRAINT `foo_bar_fk2` FOREIGN KEY (`bar_id`) REFERENCES `bar` (`bar_id`) ON DELETE CASCADE ON UPDATE CASCADE 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci COMMENT='Links between Foo and Bar'; 

J'ai les questions suivantes sur index:

  1. Est-il nécessaire de définir explicitement les index pour les clés primaires et à l'étranger?
  2. Si ce n'est pas, vous obtenez en fait deux indices (et moins de performance)?
  3. est-il différent de InnoDB et MyISAM (clés étrangères en dehors)?

Répondre

4

J'ai fait quelques expériences sur ce que vous me dit et je pensais que je partagerais comme réponse.

D'abord, je crée des tables de test:

CREATE TABLE foo (
    foo_id int(10) unsigned NOT NULL, 
    PRIMARY KEY (foo_id) 
) 
ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci; 
CREATE TABLE bar (
    bar_id int(10) unsigned NOT NULL, 
    PRIMARY KEY (bar_id) 
) 
ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci; 


CREATE TABLE foo_bar (
    foo_id int(10) unsigned NOT NULL, 
    bar_id int(10) unsigned NOT NULL 
) 
ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci; 

Jusqu'à présent, aucun index existe:

mysql> SHOW INDEXES FROM foo_bar; 
Empty set (0.00 sec) 

Ajout d'une clé primaire génère un index:

mysql> ALTER TABLE foo_bar 
    -> ADD PRIMARY KEY (`foo_id`, `bar_id`); 
Query OK, 0 rows affected (0.70 sec) 
Records: 0 Duplicates: 0 Warnings: 0 

mysql> SHOW INDEXES FROM foo_bar; 
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | 
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| foo_bar |   0 | PRIMARY |   1 | foo_id  | A   |   0 |  NULL | NULL |  | BTREE  |   | 
| foo_bar |   0 | PRIMARY |   2 | bar_id  | A   |   0 |  NULL | NULL |  | BTREE  |   | 
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
2 rows in set (0.02 sec) 

Si j'ajoute une clé étrangère sur foo_id il réutilise l'index de clé primaire puisque cette colonne est la première dans l'index:

mysql> ALTER TABLE foo_bar 
    -> ADD CONSTRAINT `foo_bar_fk1` FOREIGN KEY (`foo_id`) REFERENCES `foo` (`foo_id`) ON DELETE CASCADE ON UPDATE CASCADE; 
Query OK, 0 rows affected (0.27 sec) 
Records: 0 Duplicates: 0 Warnings: 0 

mysql> SHOW INDEXES FROM foo_bar; 
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | 
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| foo_bar |   0 | PRIMARY |   1 | foo_id  | A   |   0 |  NULL | NULL |  | BTREE  |   | 
| foo_bar |   0 | PRIMARY |   2 | bar_id  | A   |   0 |  NULL | NULL |  | BTREE  |   | 
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
2 rows in set (0.00 sec) 

Si j'ajoute une clé étrangère sur bar_id, il crée un index parce qu'aucun index existant peut être réutilisé:

mysql> ALTER TABLE foo_bar 
    -> ADD CONSTRAINT `foo_bar_fk2` FOREIGN KEY (`bar_id`) REFERENCES `bar` (`bar_id`) ON DELETE CASCADE ON UPDATE CASCADE; 
Query OK, 0 rows affected (0.25 sec) 
Records: 0 Duplicates: 0 Warnings: 0 

mysql> SHOW INDEXES FROM foo_bar; 
+---------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | 
+---------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| foo_bar |   0 | PRIMARY  |   1 | foo_id  | A   |   0 |  NULL | NULL |  | BTREE  |   | 
| foo_bar |   0 | PRIMARY  |   2 | bar_id  | A   |   0 |  NULL | NULL |  | BTREE  |   | 
| foo_bar |   1 | foo_bar_fk2 |   1 | bar_id  | A   |   0 |  NULL | NULL |  | BTREE  |   | 
+---------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
3 rows in set (0.02 sec) 

L'une de nos clés étrangères utilise l'index de clé primaire. Cela signifie que nous ne pouvons pas supprimer un tel index!

mysql> ALTER TABLE foo_bar 
    -> DROP PRIMARY KEY; 
ERROR 1025 (HY000): Error on rename of '.\test\#sql-568_c7d' to '.\test\foo_bar' (errno: 150) 

À moins de créer un index pour la clé ou nous Laisser tomber la clé elle-même étrangère:

mysql> ALTER TABLE foo_bar 
    -> DROP FOREIGN KEY `foo_bar_fk1`; 
Query OK, 0 rows affected (0.19 sec) 
Records: 0 Duplicates: 0 Warnings: 0 

mysql> ALTER TABLE foo_bar 
    -> DROP PRIMARY KEY; 
Query OK, 0 rows affected (0.23 sec) 
Records: 0 Duplicates: 0 Warnings: 0 

La conclusion est que MySQL crée des index automatiquement quand ils sont nécessaires pour une fonctionnalité (mais seulement s'ils sont strictement nécessaires).

2

Les index de clé étrangère sont utilisés pour créer referential constraints.

Ils vous permettent de définir les clauses de suppression en cascade, de sorte que la suppression d'une ligne de la table parent supprime les lignes des tables enfant. Il peut également être utilisé pour s'assurer que si vous essayez de créer une ligne dans la table enfant, elle peut être liée à un parent (Childrow.ParentId est valide)

Edit: Ah désolé j'ai mal compris. InnoDB crée automatiquement des index pour les clés étrangères. Voir does-mysql-index-foreign-key-columns-automatically

+0

Désolé si je n'ai pas expliqué correctement, ma question concerne la partie 'KEY foo_bar_fk2 (bar_id)', c'est-à-dire la définition de l'index. Le but des clés primaires et étrangères est clair. –

+0

@Alvaro. Désolé pour mon incompréhension. Réponse éditée – PaulG

1

1) les clés primaires sont automatiquement indexées dans mysql. 2) Voir ci-dessus, pas nécessaire de le faire 3) MyISAM ne supporte pas les contraintes. (Je pense que vous l'avez dit implicitement, donc c'est plus pour les autres de le lire). Certains outils graphiques comme MySQL Workbench ne provoquent pas d'alertes lorsque vous essayez d'utiliser des clés étrangères avec MyISAM, mais ne les créez évidemment pas.

BTW: Qu'est-ce que l'interface graphique utilisez-vous (sur quel système d'exploitation)?

Une bonne lecture: d ata warehousing whitepaper (contient une comparaison des tables MyISAM et InnoDB)

+1

Hmmm ... 1) Les clés étrangères sont-elles indexées automatiquement? 2) Avez-vous des index dupliqués si vous le faites quand même? 3) Je parlais des * index * - Actuellement, j'utilise une combinaison de MySQL Workbench, HeidiSQL et un éditeur de texte. –

+0

2) Je ne l'ai jamais fait, juste essayer :), mais méfiez-vous probablement que vous pouvez le faire dans votre interface graphique mais cela n'arrive jamais vraiment. 3) Moi aussi, dans MyISAM il n'y a pas de clé étrangère (contraintes) supportée. Je le disais plus explicitement au cas où d'autres se le demanderaient. –

+0

Je viens d'éditer mon post pour ajouter un lien que je cherchais tout le temps depuis que j'ai lu votre question. C'est un peu exagéré, mais c'est une bonne lecture et il y a une comparaison entre InnoDB et MyISAM dans un tableau de synthèse. il suffit de télécharger le livre blanc .pdf sur cette page. HTH –

Questions connexes