为什么MySQL在表更新期间为外键创建索引

问题描述 投票:1回答:2

文档中提供了当您使用alter table命令添加外键时,MySQL不会为外键创建索引,您需要手动创建它。

https://dev.mysql.com/doc/refman/8.0/en/create-table-foreign-keys.html

外键可以是自引用的(请参阅同一表)。当您使用ALTER TABLE将外键约束添加到表时,请记住首先创建所需的索引。

但是我使用alter table命令在表中添加了一个外键,它正在与约束一起创建索引。

ALTER TABLE `pharmaceuticals_dosage` ADD CONSTRAINT `pharmaceuticals_dosa_as_needed_reason_cod_2ac978bf_fk_human_api` FOREIGN KEY (`as_needed_reason_code_id`) REFERENCES `human_api_code` (`id`);

我认为MySQL官方文档应该没有错,所以它为什么要创建索引?

PS:上述查询由Django迁移创建

mysql django django-orm
2个回答
1
投票

您参考的文档是正确的,但不够清楚。

假设您有一张员工表。您希望每一行都有一列manager_id,这是一个外键,引用了另一行,即雇员的经理。但是出于某种原因,您不使用employee_id作为表的主键,而是使用另一个主键。

mysql> create table employees (
  id serial primary key, 
  employee_id int, 
  manager_id int
);

您想在manager_id上添加外键,引用employee_id

mysql> alter table employees add foreign key (manager_id) references employees(employee_id);
ERROR 1215 (HY000): Cannot add foreign key constraint

怎么了? employee_id上没有索引,但是外键只能引用带有索引的列。如果我们获得有关innodb状态下的外键错误的详细信息,这将更加清楚:

mysql> show engine innodb status\G
...
------------------------
LATEST FOREIGN KEY ERROR
------------------------
2019-12-26 10:25:52 0x700005bfb000 Error in foreign key constraint of table test/#sql-159d_8c9:
foreign key (manager_id) references employees(employee_id):
Cannot find an index in the referenced table where the
referenced columns appear as the first columns...
...

您需要首先在employee_id上创建索引:

mysql> alter table employees add unique key (employee_id);
Query OK, 0 rows affected (0.01 sec)

mysql> alter table employees add foreign key (manager_id) references employees(employee_id);
Query OK, 0 rows affected (0.02 sec)

因此,文档说“记住首先创建所需的索引”是正确的,但尚不清楚所需的索引是否在referenced列(employee_id)上。您假设文档正在讨论外键列(manager_id)上的必需索引。

实际上,创建外键将自动在外键列上创建索引,除非该列上的索引已经存在。


0
投票

由于您已经使用django创建了外键,它将自动创建数据库索引。在ForeignKey的文档中已提及。从文档中:

数据库索引是自动在外键上创建的>]。

您可以通过在该字段添加db_index=False来禁用外键。例如。

class SomeModel(models.Model):
    refrence_to_table = models.ForeignKey(SomeTable, db_index=False)
    # other fields

从文档附加文本:

将在ForeignKey上自动创建数据库索引。您可以通过将db_index设置为False来禁用此功能。您可能要避免如果要创建一致性的外键,则索引的开销而不是联接,或者如果您要创建替代索引例如部分或多列索引。

我想当您直接从其他表创建外键(从外壳)到其他表时,MySQL文档会参考。在此,Django将在创建时生成自定义sql。

您可以检查Django在不同的数据库操作中使用的Schema

© www.soinside.com 2019 - 2024. All rights reserved.