After running the following SQL statements, you will see that, MySQL has automatically created the non-unique index question_tag_tag_id_tag_id on the tag_id column for me after the first ALTER TABLE statement has run.
But after the second ALTER TABLE statement has run, I think MySQL should also automatically create another non-unique index question_tag_question_id_question_id on the question_id column for me.
But as you can see from the SHOW INDEXES statement output, it’s not there.
Why does MySQL forget about the second ALTER TABLE statement?
By the way, since I have already created a unique index question_id_tag_id_idx used by both question_id and tag_id columns. Is creating a separate index for each of them redundant?
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>
From the documentation:
question_idis the first column of both the primary key and thequestion_id_tag_id_idxindex. Therefore, no further index is needed for the foreign key. Thequestion_id_tag_id_idxindex is actually unnecessary because the primary key has the same columns in the same order. Primary keys are unique clustered indexes.For the
question_tag_tag_id_tag_idforeign key, an index is created because there is no existing index starting withtag_id.The reason that the
question_id_tag_id_idxindex (or the primary key) can be used for the foreign key onquestion_id, but not for the foreign key ontag_idis explained by the section on how MySQL uses indexes in the documentation:The foreign key needs to be able to quickly look up values in the referencing table (
question_tag).question_idappears first inquestion_id_tag_id_idx(is a leftmost prefix), so this index can be used.tag_idappears second, so the index cannot be used.