当 table 有索引时,LOAD DATA 呈指数级减慢

LOAD DATA exponentially slows down when table has indexes

我正在使用 LOAD DATA LOCAL INFILE 填充具有以下结构的 table:

CREATE TABLE `player_talent` (
  `player_id` int(10) unsigned NOT NULL,
  `talent_id` int(10) unsigned NOT NULL,
  `level` tinyint(4) NOT NULL,
  PRIMARY KEY (`player_id`,`level`),
  KEY `player_talent_talent_id_foreign` (`talent_id`),
  CONSTRAINT `player_talent_player_id_foreign` FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE,
  CONSTRAINT `player_talent_talent_id_foreign` FOREIGN KEY (`talent_id`) REFERENCES `talents` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

我在 Google 云上使用 MySQL 5.7,在导入之前我禁用了 binlog 并将 innodb_flush_log_at_trx_commitunique_checksforeign_key_checks 设置为0

这是我加载数据时使用的存储 space 的样子:

IOPS 始终处于最大值。在上面的图像中,导入甚至没有完成。如果我删除所有索引,然后在导入后重新创建它们,则此图如下所示:

导入阶段具有一致的线性性能。重新创建索引比导入花费的时间更长,但至少它在合理的时间内完成。

有没有办法避免手动执行此操作?我认为 LOAD DATA 应该提供最好的性能。 DISABLE KEYS 不支持 InnoDB

你说你有 250M 行,这是很多要求 MySQL 在单个语句中插入。为了提高摄取性能,我建议您将输入拆分为多个文件。

blogged 过去曾讨论过这个问题,还有一些快捷方式可以更轻松地将文件分成更小的部分。我会说每个文件应该是 100 万行或更小。

您还可以找到其他好的建议 here and here 来调整 MySQL 以提高批量导入性能。