mysql - 为什么这个组合键没有被索引?

标签 mysql

我创建了这个表:

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/

相关文章:

mysql - 获取客户行的总和

MySQL 组合数据 + 计数(*) 查询 2 个表

php - 徽章原因错误

php - 如何在查询结果中显示多个结果?

php - SQL - 如果该行不存在,则插入行并从其他行选择

android - 如何将 SQLite 创建的数据上传到 MySQL 服务器?

php - PHP 和 MD5 哈希中的更改密码脚本

php - 在 PHP 中将数据插入数据库

C# 日期时间 MySQL 命令

mysql - 为什么插入查询在 Laravel 5 中不起作用