我创建了这个表:
CREATE TABLE incident_originator (
id_incident INT (11) UNSIGNED NOT NULL,
id_user INT (11) NOT NULL,
PRIMARY KEY (
id_incident,
id_user
),
CONSTRAINT fk_incident_incident_originator FOREIGN KEY (id_incident) REFERENCES incident_table (id_incident) ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT fk_user_incident_originator FOREIGN KEY (id_user) REFERENCES users (id_user) ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE = INNODB DEFAULT CHARSET = latin1;
然而,fk_user_incident_originator
已编入索引,而 fk_incident_incident_originator
未编入索引。这是为什么? InnoBD 不是应该自动索引所有外键吗? id_incident
中缺少索引会使连接变慢,不是吗?越看越不懂……
另外,当我向表中添加值时,它们按第二列排序,作为人类阅读起来会很奇怪。
编辑:当我执行 SHOW INDEX FROM incident_originator;
时,它返回:
Non_unique Key_name Seq_in_index Column_name
0 PRIMARY 1 id_incident
0 PRIMARY 2 id_user
1 fk_user_incident_originator 1 id_user
最佳答案
fk_incident_incident_originator
is not
当然是。
PRIMARY KEY (id_incident,id_user),
In the referencing table, there must be an index where the foreign key columns are listed as the first columns in the same order. Such an index is created on the referencing table automatically if it does not exist.
https://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html
id_incident
是主键的第一列(意思是最左边的)...并且主键是在强制执行约束时查找值的完美索引。添加第二个索引是多余的。
连接也是如此(尽管连接并不是外键总是被索引的真正原因)——任何包含锚定在索引左侧的所有连接列的索引对于连接都是非常有效的。
they are ordered by the second column and it gets weird to read as a human being.
告诉任何人您知道数据库不会为了人类的利益而对其输出进行排序,除非人类使用 ORDER BY
。没有 ORDER BY
的结果集根据定义是无序的。行通常按主键顺序返回的事实是巧合,而不是设计或必然。当表变大时,这种行为可能会发生变化,因为优化器在读取表时会更改策略...但是由于 id_user
上的索引实际上是一个覆盖索引(它包含表中的所有列,因为所有索引还包含主键的副本......或者更准确地说,它包含满足此特定查询所需的所有列 - 有时这是两种不同的东西,这是不使用的最佳理由之一SELECT *
在你的实际代码中)所以优化器恰好选择它作为它的源。它从它选择的任何索引中按索引顺序读取行,并且该顺序成为结果的完全巧合的顺序。
关于mysql - 为什么这个组合键没有被索引?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42549405/