Mysql 主键和外键上的索引

Mysql 主键和外键上的索引,mysql,Mysql,我使用GUI工具创建了一个数据库,我注意到键(又称索引)定义的使用似乎不一致: CREATE TABLE `foo_bar` ( `foo_id` int(10) unsigned NOT NULL, `bar_id` int(10) unsigned NOT NULL, PRIMARY KEY (`foo_id`, `bar_id`), KEY `foo_bar_fk2` (`bar_id`), -- <== ??? CONSTRAINT `foo_bar_fk1`

我使用GUI工具创建了一个数据库,我注意到
(又称
索引
)定义的使用似乎不一致:

CREATE TABLE `foo_bar` (
  `foo_id` int(10) unsigned NOT NULL,
  `bar_id` int(10) unsigned NOT NULL,
  PRIMARY KEY (`foo_id`, `bar_id`),
  KEY `foo_bar_fk2` (`bar_id`), -- <== ???
  CONSTRAINT `foo_bar_fk1` FOREIGN KEY (`foo_id`) REFERENCES `foo` (`foo_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `foo_bar_fk2` FOREIGN KEY (`bar_id`) REFERENCES `bar` (`bar_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci COMMENT='Links between Foo and Bar';
CREATE TABLE`foo_bar`(
`foo_id`int(10)无符号非空,
`bar_id`int(10)无符号非空,
主键(`foo\u id`、`bar\u id`),

键'foo\u bar\u fk2'('bar\u id'),--外键索引用于创建

它们允许您定义级联删除子句,以便从父表中删除行将从子表中删除行。它还可用于确保如果您尝试在子表中创建行,它可以链接到父表(即
Childrow.ParentId
有效)

编辑:啊,对不起,我误解了。InnoDB会自动为外键创建索引。请参见

1)主键会在mysql中自动索引。 2) 见上文,不必这样做 3) MyISAM不支持约束。(我想你暗示了这一点,所以这更适合其他人阅读)。一些图形工具(如MySQL Workbench)在尝试将外键用于MyISAM时不会引起警报,但显然不会创建它们

顺便问一下:你在使用什么图形用户界面(在哪个操作系统上)


好的读物:d(包含MyISAM和InnoDB表的比较)

我一直在做一些实验,以验证您告诉我的内容,我想我会将其作为答案与大家分享

首先,我创建一些测试表:

CREATE TABLE foo (
    foo_id int(10) unsigned NOT NULL,
    PRIMARY KEY (foo_id)
)
ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci;
CREATE TABLE bar (
    bar_id int(10) unsigned NOT NULL,
    PRIMARY KEY (bar_id)
)
ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci;


CREATE TABLE foo_bar (
    foo_id int(10) unsigned NOT NULL,
    bar_id int(10) unsigned NOT NULL
)
ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci;
到目前为止,没有索引:

mysql> SHOW INDEXES FROM foo_bar;
Empty set (0.00 sec)
添加主键将生成索引:

mysql> ALTER TABLE foo_bar
    -> ADD PRIMARY KEY (`foo_id`, `bar_id`);
Query OK, 0 rows affected (0.70 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> SHOW INDEXES FROM foo_bar;
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table   | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| foo_bar |          0 | PRIMARY  |            1 | foo_id      | A         |           0 |     NULL | NULL   |      | BTREE      |         |
| foo_bar |          0 | PRIMARY  |            2 | bar_id      | A         |           0 |     NULL | NULL   |      | BTREE      |         |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
2 rows in set (0.02 sec)
如果我在
foo_id
上添加外键,它将重用主键索引,因为该列是索引中的第一列:

mysql> ALTER TABLE foo_bar
    -> ADD CONSTRAINT `foo_bar_fk1` FOREIGN KEY (`foo_id`) REFERENCES `foo` (`foo_id`) ON DELETE CASCADE ON UPDATE CASCADE;
Query OK, 0 rows affected (0.27 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> SHOW INDEXES FROM foo_bar;
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table   | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| foo_bar |          0 | PRIMARY  |            1 | foo_id      | A         |           0 |     NULL | NULL   |      | BTREE      |         |
| foo_bar |          0 | PRIMARY  |            2 | bar_id      | A         |           0 |     NULL | NULL   |      | BTREE      |         |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
2 rows in set (0.00 sec)
如果我在
bar\u id
上添加外键,它会创建一个索引,因为现有索引无法重用:

mysql> ALTER TABLE foo_bar
    -> ADD CONSTRAINT `foo_bar_fk2` FOREIGN KEY (`bar_id`) REFERENCES `bar` (`bar_id`) ON DELETE CASCADE ON UPDATE CASCADE;
Query OK, 0 rows affected (0.25 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> SHOW INDEXES FROM foo_bar;
+---------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table   | Non_unique | Key_name    | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+---------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| foo_bar |          0 | PRIMARY     |            1 | foo_id      | A         |           0 |     NULL | NULL   |      | BTREE      |         |
| foo_bar |          0 | PRIMARY     |            2 | bar_id      | A         |           0 |     NULL | NULL   |      | BTREE      |         |
| foo_bar |          1 | foo_bar_fk2 |            1 | bar_id      | A         |           0 |     NULL | NULL   |      | BTREE      |         |
+---------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
3 rows in set (0.02 sec)
我们的外键之一是使用主键索引。这意味着我们不能删除这样的索引

mysql> ALTER TABLE foo_bar
    -> DROP PRIMARY KEY;
ERROR 1025 (HY000): Error on rename of '.\test\#sql-568_c7d' to '.\test\foo_bar' (errno: 150)
除非我们为外键创建索引或删除键本身:

mysql> ALTER TABLE foo_bar
    -> DROP FOREIGN KEY `foo_bar_fk1`;
Query OK, 0 rows affected (0.19 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> ALTER TABLE foo_bar
    -> DROP PRIMARY KEY;
Query OK, 0 rows affected (0.23 sec)
Records: 0  Duplicates: 0  Warnings: 0


结论是MySQL会在功能需要索引时自动创建索引(但只有在严格必要时才会创建)。

如果我没有正确解释,很抱歉,我的问题是关于
键foo\u bar\u fk2(bar\u id)
部分,即索引定义。主键和外键的用途是明确的。。。1) 外键也会自动编入索引吗?2) 如果仍然这样做,是否会得到重复的索引?3) 我说的是索引——现在,我使用的是MySQL Workbench、HeidiSQL和文本编辑器的组合。2)我从来没有这样做过,只是尝试一下:),但请注意,也许你可以在GUI中这样做,但它从来没有真正发生过。3) 我也是,在MyISAM中不支持外键(约束)。我只是说得更清楚一些,以防其他人怀疑。我只是编辑了我的帖子,添加了一个自从我读了你的问题以来一直在寻找的链接。这有点过分了,但它是一本很好的读物,在概览表中对InnoDB和MyISAM进行了比较。只需下载该页面上的.pdf白皮书。嗯