我有以下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约束。
答案 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 |
更多链接