MySQL忘记了为外键自动创建索引了吗?

MySQL忘记了为外键自动创建索引了吗?,mysql,database-design,indexing,foreign-keys,innodb,Mysql,Database Design,Indexing,Foreign Keys,Innodb,运行以下SQL语句后,您将看到,MySQL在运行第一个

运行以下SQL语句后,您将看到,MySQL在运行第一个
语句后,在
tag\u id
列上为我自动创建了非唯一索引
question\u tag\u id\u tag\u id

但是在第二个
altertable
语句运行之后,我认为MySQL还应该为我在
问题id
列上自动创建另一个非唯一索引
问题标签\问题id \问题id

但是,正如您从
SHOW index
语句输出中看到的,它不在那里

为什么MySQL忘记了第二个ALTERTABLE语句

顺便说一下,因为我已经创建了一个唯一的索引
question\u id\u tag\u id\u idx
,由两个
question\u id
tag\u 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>
从:

必须有一个索引,其中 外键列作为 按相同顺序排列的第一列。这样的 将在引用对象上创建索引 如果没有,则自动创建表 存在

question\u id
是主键和
question\u id\u标记\u id\u idx
索引的第一列。因此,外键不需要进一步的索引。实际上不需要
question\u id\u tag\u id\u idx
索引,因为主键具有相同顺序的相同列。主键是唯一的

对于
question\u tag\u tag\u id\u tag\u id
外键,将创建索引,因为没有以
tag\u id
开头的现有索引

文档中关于的章节解释了
question\u id\u tag\u id\u idx
索引(或主键)可用于
question\u id
上的外键,但不能用于
tag\u id
上的外键的原因:

如果表有多列 索引,索引的任何最左侧前缀 优化器可以使用索引来 查找行。例如,如果您有 上的三列索引(col1、col2、, col3),您已经索引了搜索 (第1列)、(第1列、第2列)上的能力, 和(col1,col2,col3)


外键需要能够快速查找引用表中的值(
question\u tag
question\u id
首先出现在
question\u id\u tag\u id\u idx
中(是最左边的前缀),因此可以使用此索引
tag_id
出现在第二列,因此无法使用索引。

在多列索引中,我相信您可以免费获得第一列的索引,就好像只有该列上有索引一样


更新:正如另一位回答者所指出的,这只是特定索引的情况,它们是非空的并成为“聚集索引”。我明白了,这意味着我不必创建
question\u id\u tag\u id\u idx
索引,因为
question\u id
列是聚集索引中最左边的前缀模式之一,它已经可以通过问题id在
question\u tag
表中快速查找记录。但是
tag\u id
列不是,这就是为什么它需要一个单独的索引,以便在
question\u tag
表中按标记id快速查找。这是否正确?@bobobo
question\u id\u tag\u id\u idx
不需要,因为它只是复制主键。
tag\u id
需要单独的索引,因为它不会出现在
question\u id\u tag\u id\u idx
索引或主键的开头。