删除MySQL中用于外键的索引的后果

时间:2017-11-02 19:22:49

标签: mysql indexing foreign-keys

似乎可以删除在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.方可视化工具)

2 个答案:

答案 0 :(得分:1)

这似乎是错误#16896810。显然,5.7.2 (2013-09-21, Milestone 12)之后5.7.9 (2015-10-21, General Availability)修正了此问题。它也在MySQL 5.6.14 (2013-09-20, General Availability)

中修复
  
      
  • InnoDB:当删除具有多个索引的列上的所有索引时,InnoDB在外键约束需要索引时无法阻止DROP INDEX操作。 (Bug#16896810)
  •   

这并没有明确说明该修复程序适用于foreign_key_checks=OFF,但DROP时未允许foreign_key_checks=ON,因此大概是OFF定影

尽管允许DROP INDEX,但重新启动服务器correctly gives a missing foreign key index error。所以利用这个bug并不会让你处于一个非常有用的状态。当然你可以自动删除它;但由于它是一个错误,你不能依赖于这种行为,你不应该期望/猜测你的系统如何在其下行动,无论其他问题是记录/观察到的还是未记录/观察到的。无论如何,出于完整性的目的,您应该通过DBMS以这种或那种方式强制执行与该外键声明相关的约束 - 不要强制执行它或依赖于应用程序。

(与往常一样,Minimal, Complete, and Verifiable Example会有所帮助。)

答案 1 :(得分:0)

如果未强制执行FK,其中一个缺点与查询性能无关。

如果您可以将值插入到commands中其引用的PK列中不存在的FK列中,那么您将不知道您的数据是否有任何好处。它可能包含一堆破损的参考文献,你无法阻止它们发生。

外键约束 -it的目的是保持数据完整性。