MySQL是不是自动索引外键列?

Posted

技术标签:

【中文标题】MySQL是不是自动索引外键列?【英文标题】:Does MySQL index foreign key columns automatically?MySQL是否自动索引外键列? 【发布时间】:2010-09-23 04:33:45 【问题描述】:

mysql 会自动索引外键列吗?

【问题讨论】:

【参考方案1】:

是的,但仅限于innodb。 Innodb 是目前唯一实现了外键的表格式。

【讨论】:

你有任何理由相信 MySQL 将允许任何其他表类型的非索引列上的外键? 我真的无法回答。您可能想查找将在 MySQL 6.0 中发布的 Maria 和 Falcon 存储引擎,看看它们是否支持非索引列上的外键。 显然这不是真的。我有一个大表(100 万条记录)和 count(*) where fkey=?需要 15 秒。在 fkey 列上添加了一个索引,现在事情不到一秒钟。 用另一个表和 1000 万条记录进行相同的实验。这是ofc MySQL 5.1 InnoDB。该表有三个字段,一个是主键整数,另一个是已经索引的。第三个是另一个表的主键的外键。在不添加显式索引的情况下,查找需要几秒钟。 Show index from table 也没有显示索引。 @AbiusX 5.1 可能太旧了,请参阅下面 MrAlexander 的回答。【参考方案2】:

显然,索引是按照the link robert has posted 中的指定自动创建的。

InnoDB 需要外键和引用键的索引,以便外键检查可以快速且不需要表扫描。在引用表中,必须有一个索引,其中外键列按相同顺序列为第一列。 如果引用表不存在,则会在引用表上自动创建此类索引。(这与某些旧版本相反,其中索引必须显式创建,否则创建外键约束会失败.) index_name,如果给定,如前所述使用。

InnoDB and FOREIGN KEY Constraints

【讨论】:

+1 比被选为提供文档证明的答案要好得多 引用的文本似乎不再包含在 MySQL 文档中,因此不清楚这是否仍然正确。 @user2045006 您可以参考doc 5.0 以及doc 5.6 以获得准确的引用文本 在当前的文档中,只是文字略有变化(我猜意思差不多):InnoDB permits a foreign key to reference any index column or group of columns. However, in the referenced table, there must be an index where the referenced columns are the first columns in the same order. 【参考方案3】:

是的,请参阅InnoDB and FOREIGN KEY Constraints。

【讨论】:

这个答案是一个很好的例子,说明为什么一个答案永远不应该只包含一个可能答案的链接。此时,链接页面根本没有回答问题。 请将所有信息添加到答案本身,而不是仅发布链接【参考方案4】:

如果您执行 ALTER TABLE(而不是 CREATE TABLE),则不会自动获取索引,至少根据 the docs (该链接适用于 5.1,但适用于 5.5):

[...] 当您使用 ALTER TABLE 向表添加外键约束时,请记住首先创建所需的索引。

【讨论】:

我还尝试了 MySQL 5.6 和 MariaDB 10,并且 ALTER TABLE 创建了一个索引。有趣的是 mysqlindexcheck 将该索引报告为“冗余索引”。我试图删除它,但出现以下错误:“ERROR 1553 (HY000): Cannot drop index 'index_name': required in a foreign key constraint”。因此,不可能删除该索引并保留外键。 您可能需要修改您的答案。 MySQL总是创建一个索引来加速外键检查如果一个不存在。文档试图告诉您在外键约束之前创建索引可能会加快速度。例如,InnoDB 可以使用可以用作外键检查索引的复合键索引,而不是自动生成冗余索引。【参考方案5】:

对于那些正在寻找来自5.7docs的报价的人:

MySQL 需要外键和引用键的索引,以便 外键检查可以很快并且不需要表扫描。在里面 引用表,必须有外键所在的索引 列按相同顺序列为第一列。这样一个 如果没有,则在引用表上自动创建索引 存在。如果您创建,此索引可能会在稍后被静默删除 另一个可用于强制外键约束的索引。 index_name,如果给定,则如前所述使用。

【讨论】:

【参考方案6】:

如前所述,它适用于 InnoDB。起初我觉得奇怪的是许多其他(特别是 MS SQL 和 DB2)没有。只有在表行很少时,表空间扫描才比索引扫描好 - 所以在绝大多数情况下,外键都希望被索引。然后它有点打击我——这并不一定意味着它必须是一个独立的(一列)索引——它在 MySQL 的自动 FK 索引中。所以,这可能是 MS SQL、DB2(我不确定 Oracle)等将其留给 DBA 的原因;毕竟大型表上的多个索引可能会导致性能和空间问题。

【讨论】:

你提出了一个关于复合键索引的好观点;但是,如果新创建的复合键索引履行了快速进行外键检查的义务,MySQL 将自动/静默删除自动生成的单键索引。老实说,我不知道为什么 MS SQL、DB2 和其他人不这样做。他们没有什么借口。我想不出一个自动生成的外键索引会有害的用例。【参考方案7】:

是的,Innodb 提供这个。您可以在FOREIGN KEY 子句之后放置一个外键名称,或者让 MySQL 为您创建一个名称。 MySQL 自动创建一个名称为foreign_key_name 的索引。

CONSTRAINT constraint_name
FOREIGN KEY foreign_key_name (columns)
REFERENCES parent_table(columns)
ON DELETE action
ON UPDATE action

【讨论】:

【参考方案8】:

无法自动获取索引键

ALTER TABLE (NAME OF THE TABLE) ADD INDEX (FOREIGN KEY)

您创建的表的名称,例如照片和 FOREIGN KEY,例如 photograph_id。代码应该是这样的

ALTER TABLE photographs ADD INDEX (photograph_id);

【讨论】:

以上是关于MySQL是不是自动索引外键列?的主要内容,如果未能解决你的问题,请参考以下文章

Django 会自动为外键列生成索引吗?

MySQL创建数据表并建立主外键关系

MySQL创建数据表并建立主外键关系

mysql 主键和唯一索引的区别

MySQL外键使用及说明详解

MYSQL外键(Foreign Key)的使用