【发布时间】:2018-04-15 10:32:05
【问题描述】:
似乎可以删除为 MySQL 5.5 中的外键创建的索引,使用如下所示的小“技巧”:
mysql > create table commands (
id int primary key auto_increment, name varchar(255));
mysql > create table data (
dim_command int, cnt int NOT NULL,
CONSTRAINT FOREIGN KEY (dim_command) references commands(id));
现在创建了一个无法删除的索引:
mysql > show create table data;
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| data | CREATE TABLE `data` (
`dim_command` int(11) DEFAULT NULL,
`cnt` int(11) NOT NULL,
KEY `dim_command` (`dim_command`),
CONSTRAINT `data_ibfk_1` FOREIGN KEY (`dim_command`) REFERENCES `commands` (`id`)
) ENGINE=InnoDB
mysql > alter table data drop index dim_command;
ERROR 1553 (HY000): Cannot drop index 'dim_command': needed in a foreign key constraint
但它可以被欺骗移除:
mysql > set foreign_key_checks=Off;
Query OK, 0 rows affected (0.00 sec)
mysql > alter table data drop index dim_command;
Query OK, 0 rows affected (0.51 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql > set foreign_key_checks=On;
Query OK, 0 rows affected (0.00 sec)
此时:
-
data表仍然具有外键约束规范(通过执行例如show create table data来显示) - 但似乎没有强制执行该约束,即可以
将行插入到引用不存在的行的
data表中commands表。
我的问题是,以这种方式在 InnoDB 表上删除用于外键约束的索引是否还有其他后果?
(背景是我有一个数据仓库,其中有人将外键添加到包含数亿行的事实表中,该表引用了只有少数行的其他表 - 使此类列上的索引对查询无用性能,同时占用 大量 磁盘空间并严重影响插入性能。完整性不太受关注,由数据仓库中的 ETL 过程强制执行 - 但保持外键约束对于文档和 3. 派对可视化工具)
【问题讨论】:
-
几年前,我遇到过这样一种情况,我们在关闭外键检查的情况下对表进行了一些结构性工作,结果导致表陷入了未完成的状态表现如预期。 mysql 守护程序之类的东西无法重新启动,或者无法删除并重新创建表......,抱歉,我记不清了。无论如何,我只想说,你正在徘徊在我相信 mysql 开发人员无意让你旅行的水域中。如果您从不查询这些列,我只需删除外键并为文档添加列注释。
-
呼应 Jeff Richards... 我的建议是 DROP 外键约束。对于文档,请添加列注释。对于我们没有定义外键的事实表,对于列注释,我们使用单词“
ref”,后跟引用的 table_name.column_name,例如COMMENT 'ref customer.id'。 (你问了一个有趣的问题,但这个问题我永远不想知道答案。我永远不想在薄冰的湖里那么远。 -
哦,FK 的缺点。人们仍然使用它们是一个奇迹。
DROP约束。处理应用程序中的完整性。
标签: mysql indexing foreign-keys