mysql InnoDB:FOREIGN KEY约束性能

时间:2015-12-13 17:28:37

标签: mysql performance foreign-keys innodb

我有以下InnoDB表:

 CREATE TABLE `vehicle` (
  `ID` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
  `Name` varchar(50) DEFAULT NULL,
  `Model` varchar(100) DEFAULT NULL,
  `Engine_Type` varchar(70) DEFAULT NULL,
  `Construction_From` date DEFAULT NULL,
  `Construction_To` date DEFAULT NULL,
  `Engine_Power_KW` mediumint(8) unsigned DEFAULT NULL,
  `Engine_Power_HP` mediumint(8) unsigned DEFAULT NULL,
  `CC` mediumint(8) unsigned DEFAULT NULL,
  `TTC_TYP_ID` int(11) unsigned DEFAULT NULL,
  `Vehicle_Type` tinyint(1) DEFAULT NULL,
  `ID_Body_Type` tinyint(3) unsigned DEFAULT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=49407 DEFAULT CHARSET=utf8;

CREATE TABLE `part` (
  `ID` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `ID_Brand` smallint(5) unsigned DEFAULT NULL,
  `Code_Full` varchar(50) DEFAULT NULL,
  `Code_Condensed` varchar(50) DEFAULT NULL,
  `Ean` varchar(50) DEFAULT NULL COMMENT 'The part barcode.',
  `TTC_ART_ID` int(11) unsigned DEFAULT NULL COMMENT 'TecDoc ID.',
  `ID_Product_Status` tinyint(3) unsigned DEFAULT NULL,
  PRIMARY KEY (`ID`),
  UNIQUE KEY `TTC_ART_ID_UNIQUE` (`TTC_ART_ID`),
  UNIQUE KEY `ID_Brand_Code_Full_UNIQUE` (`ID_Brand`,`Code_Full`)
) ENGINE=InnoDB AUTO_INCREMENT=3732260 DEFAULT CHARSET=utf8;

CREATE TABLE `vehicle_part` (
  `ID_Vehicle` mediumint(8) unsigned NOT NULL,
  `ID_Part` int(11) unsigned NOT NULL,
  PRIMARY KEY (`ID_Vehicle`,`ID_Part`),
  KEY `fk_vehicle_part_vehicle_id_vehicle_idx` (`ID_Vehicle`),
  KEY `fk_vehicle_part_part_id_part_idx` (`ID_Part`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

表车辆有大约45.000条记录,表格部分有大约3.500.000条记录,而表格vehicle_part有大约100.000.000条记录。 为 vehicle_part 创建二级索引并不需要太长时间,两者都需要大约30分钟。 我不能做的是创建外键约束:例如

ALTER TABLE `vehicle_part` 
ADD CONSTRAINT `fk_vehicle_part_vehicle_id_vehicle`
  FOREIGN KEY (`ID_Vehicle`)
  REFERENCES `vehicle` (`ID`)
  ON DELETE NO ACTION
  ON UPDATE NO ACTION;

需要很长时间才能完成。我知道该表是重建的,因为它占用了大量的磁盘空间。我该怎么做才能提高性能? 如果我使用fk约束创建表,然后添加记录,则vehicle_part中的插入过程也需要很长时间(大约3天)。 我正在使用4GB RAM的笔记本电脑。

编辑12/01/2016

Drew给出的答案在很大程度上有助于提高性能。我使用SELECT ... INTO outfile更改了每个脚本,然后从导出的csv文件中更改了LOAD DATA INFILE。有时在LOAD DATA INFILE之前删除索引并在加载过程后重新创建它们可以节省更多时间。没有必要只删除辅助索引的fk约束。

1 个答案:

答案 0 :(得分:2)

如果您从FK的角度了解您的数据是原始的,那么按照注释中的建议建立没有二级索引的结构,但是模式中的FK仍然暂时禁用FK检查。

加载您的数据。如果是外部数据,肯定是用LOAD DATA INFILE。

加载数据后,启用FK检查。并使用Alter Table建立二级索引。

再次,假设您的数据是干净的。还有其他方法证明事后风险不利。

create table student
(   id int auto_increment primary key,
    sName varchar(100) not null
    -- secondary indexes to be added later
);

create table booksAssigned
(   id int auto_increment primary key,
    studentId int not null,
    isbn varchar(20) not null,
    constraint foreign key `fk_b_s` (studentId) references student(id)
    -- secondary indexes to be added later
);


insert booksAssigned(studentId,isbn) values (1,'asdf'); -- Error 1452 as expected

set FOREIGN_KEY_CHECKS=0; -- turn FK checks of temporarily

insert booksAssigned(studentId,isbn) values (1,'asdf'); -- Error 1452 as expected

set FOREIGN_KEY_CHECKS=1; -- succeeds despite faulty data

insert booksAssigned(studentId,isbn) values (2,'38383-asdf'); -- Error 1452 as expected

根据操作说明,如何在初始架构创建后删除引用表中的自动生成索引:

mysql> show create table booksAssigned;

| booksAssigned | CREATE TABLE `booksassigned` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `studentId` int(11) NOT NULL,
  `isbn` varchar(20) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `fk_b_s` (`studentId`),
  CONSTRAINT `booksassigned_ibfk_1` FOREIGN KEY (`studentId`) REFERENCES `student` (`id`)
) ENGINE=InnoDB |

mysql> set FOREIGN_KEY_CHECKS=0;
Query OK, 0 rows affected (0.00 sec)

mysql> drop index `fk_b_s` on booksAssigned;
Query OK, 0 rows affected (0.49 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show create table booksAssigned;

| booksAssigned | CREATE TABLE `booksassigned` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `studentId` int(11) NOT NULL,
  `isbn` varchar(20) NOT NULL,
  PRIMARY KEY (`id`),
  CONSTRAINT `booksassigned_ibfk_1` FOREIGN KEY (`studentId`) REFERENCES `student` (`id`)
) ENGINE=InnoDB |

更多链接