MySQL забыл об автоматическом создании индекса для внешнего ключа? - PullRequest
2 голосов
/ 12 марта 2010

После выполнения следующих операторов SQL вы увидите, что MySQL автоматически создал для меня неуникальный индекс question_tag_tag_id_tag_id для столбца tag_id после выполнения оператора first ALTER TABLE .

Но после выполнения оператора second ALTER TABLE я думаю, что MySQL также должен автоматически создать еще один неуникальный индекс question_tag_question_id_question_id для столбца question_id.

Но, как видно из вывода оператора SHOW INDEXES, его там нет.

Почему MySQL забывает о втором ALTER TABLE утверждении?

Кстати, поскольку я уже создал уникальный индекс question_id_tag_id_idx, используемый в обоих столбцах question_id и tag_id. Является ли создание отдельного индекса для каждого из них излишним?

mysql> DROP DATABASE mydatabase;
Query OK, 1 row affected (0.00 sec)

mysql> CREATE DATABASE mydatabase;
Query OK, 1 row affected (0.00 sec)

mysql> USE mydatabase;
Database changed
mysql> CREATE TABLE question (id BIGINT AUTO_INCREMENT, html TEXT, PRIMARY KEY(id)) ENGINE = INNODB;
Query OK, 0 rows affected (0.05 sec)

mysql> CREATE TABLE tag (id BIGINT AUTO_INCREMENT, name VARCHAR(10) NOT NULL, UNIQUE INDEX name_idx (name), PRIMARY KEY(id)) ENGINE = INNODB;
Query OK, 0 rows affected (0.05 sec)

mysql> CREATE TABLE question_tag (question_id BIGINT, tag_id BIGINT, UNIQUE INDEX question_id_tag_id_idx (question_id, tag_id), PRIMARY KEY(question_id, tag_id)) ENGINE = INNODB;
Query OK, 0 rows affected (0.00 sec)

mysql> ALTER TABLE question_tag ADD CONSTRAINT question_tag_tag_id_tag_id FOREIGN KEY (tag_id) REFERENCES tag(id);
Query OK, 0 rows affected (0.10 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> ALTER TABLE question_tag ADD CONSTRAINT question_tag_question_id_question_id FOREIGN KEY (question_id) REFERENCES question(id);
Query OK, 0 rows affected (0.13 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> SHOW INDEXES FROM question_tag;
+--------------+------------+----------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table        | Non_unique | Key_name                   | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+--------------+------------+----------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| question_tag |          0 | PRIMARY                    |            1 | question_id | A         |           0 |     NULL | NULL   |      | BTREE      |         |
| question_tag |          0 | PRIMARY                    |            2 | tag_id      | A         |           0 |     NULL | NULL   |      | BTREE      |         |
| question_tag |          0 | question_id_tag_id_idx     |            1 | question_id | A         |           0 |     NULL | NULL   |      | BTREE      |         |
| question_tag |          0 | question_id_tag_id_idx     |            2 | tag_id      | A         |           0 |     NULL | NULL   |      | BTREE      |         |
| question_tag |          1 | question_tag_tag_id_tag_id |            1 | tag_id      | A         |           0 |     NULL | NULL   |      | BTREE      |         |
+--------------+------------+----------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
5 rows in set (0.01 sec)

mysql>

Ответы [ 2 ]

2 голосов
/ 12 марта 2010

Из документации :

Должен быть индекс, в котором столбцы внешнего ключа перечислены в качестве первых столбцов в том же порядке.Такой индекс создается в ссылочной таблице автоматически, если он не существует.

question_id - это первый столбец первичного ключа и индекса question_id_tag_id_idx.Следовательно, для внешнего ключа не требуется никаких дополнительных индексов.Индекс question_id_tag_id_idx на самом деле не нужен, поскольку первичный ключ имеет одинаковые столбцы в том же порядке.Первичные ключи являются уникальными кластеризованными индексами .

Для внешнего ключа question_tag_tag_id_tag_id создается индекс, поскольку не существует никакого индекса, начинающегося с tag_id.

.Причина, по которой индекс question_id_tag_id_idx (или первичный ключ) может использоваться для внешнего ключа на question_id, но не для внешнего ключа на tag_id, объясняется в разделе на , как MySQL использует индексы в документации:

Если таблица имеет индекс из нескольких столбцов, любой крайний левый префикс индекса может быть использован оптимизатором для поиска строк.Например, если у вас есть индекс из трех столбцов (col1, col2, col3), у вас есть индексированные возможности поиска для (col1), (col1, col2) и (col1, col2, col3).

Внешний ключ должен иметь возможность быстрого поиска значений в справочной таблице (question_tag).question_id появляется первым в question_id_tag_id_idx (это самый левый префикс), поэтому этот индекс можно использовать.tag_id появляется вторым, поэтому индекс не может быть использован.

1 голос
/ 12 марта 2010

В многоколоночном индексе, я полагаю, вы получаете индекс первого столбца бесплатно, как если бы индекс был только для этого столбца.

Обновление: это касается только определенных индексов, как указывал другой ответчик, которые не равны NULL и становятся "кластерными индексами".

...