Tôi đang thực hiện một số thử nghiệm về những gì bạn đã nói với tôi và tôi nghĩ rằng mình sẽ chia sẻ nó như một câu trả lời.
Đầu tiên, tôi tạo một số bảng thử nghiệm:
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;
Cho đến nay, không có chỉ mục nào tồn tại:
mysql> SHOW INDEXES FROM foo_bar;
Empty set (0.00 sec)
Thêm khóa chính sẽ tạo chỉ mục:
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)
Nếu tôi thêm khóa ngoại trên foo_id
nó sử dụng lại chỉ mục khóa chính vì cột đó là cột đầu tiên trong chỉ mục:
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)
Nếu tôi thêm khóa ngoại trên bar_id
, nó tạo ra một chỉ mục vì không có chỉ mục hiện có nào có thể được sử dụng lại:
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)
Một trong những khóa ngoại của chúng tôi đang sử dụng chỉ mục khóa chính. Điều đó có nghĩa là chúng tôi không thể xóa chỉ mục đó!
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)
Trừ khi chúng tôi tạo chỉ mục cho khóa ngoại hoặc chúng tôi đánh rơi chính khóa đó:
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
Kết luận là MySQL tạo chỉ mục tự động khi chúng được yêu cầu cho một chức năng (nhưng chỉ khi chúng thực sự cần thiết).