【发布时间】:2016-03-19 04:00:37
【问题描述】:
我有以下 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;
表vehicle 有大约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 的笔记本电脑。
编辑 2016 年 12 月 1 日
Drew 给出的答案对显着提高性能有很大帮助。我使用 SELECT ... INTO outfile 更改了每个脚本,然后从导出的 csv 文件中加载数据。有时在 LOAD DATA INFILE 之前删除索引并在加载过程之后重新创建它们可以节省更多时间。不需要只删除二级索引的 fk 约束。
【问题讨论】:
-
一个小提示......在索引表中插入大量数据会降低性能......如果您可以删除索引然后插入然后再次构建索引,性能将大大提高
-
是的,这就是我所做的,并且性能有所提高,但主要问题不是索引而是外键约束。
-
为什么不考虑对表进行分区,在分区上循环,按分区插入数据
-
我对 FK 的看法?调试你的代码;那么你就不需要 FK 检查了。
-
@osamayaccoub - 添加
PARTITIONing需要很长时间,而且不会有任何帮助。
标签: mysql performance foreign-keys innodb