在大表上“创建唯一索引”花费太长时间

Nar*_*mus 6 mysql myisam index unique-constraint mysql-5.7

我正在尝试恢复 GHTorrent 的数据库转储(包含 GitHub 元数据的 CSV 文件)。该commits表拥有超过 8.91 亿行,并且project_commits拥有超过 54 亿行。由于这些表相当大,我必须使用LOAD DATA INFILE外键检查来加载它们。我正在使用MyISAM引擎。将记录导入表后,我尝试为这些表创建索引。

我正在为表运行以下 mysql 命令commits,但它在超过 12 小时内才完成。

CREATE UNIQUE INDEX `sha` ON `ghtorrent_restore`.`commits` (`sha` ASC)  COMMENT '';
Run Code Online (Sandbox Code Playgroud)

提交表如下所示:

在此输入图像描述

my.cnf我已阅读有关缓慢索引的其他 stackexchange 问题,并在目录中的文件中设置以下内容/etc/mysql

[mysqld]
bulk_insert_buffer_size=1G
myisam_sort_buffer_size=8G
key_buffer_size=6G
sort_buffer_size=10M
Run Code Online (Sandbox Code Playgroud)

由于上一个命令没有及时完成,我不得不从控制台使用 ctrl+z 来停止它。我检查了 MySQL Workbench 上的表,它没有显示为损坏,但它显示索引长度约为 36GB。

在此输入图像描述

导入该表大约需要 25 分钟,因此我预计索引不会超过一个小时,但我现在运行“创建唯一索引”命令大约 2 小时,没有任何进展迹象。

当我运行该命令时,mysqld 占用大量 cpu 并且不断占用内存。达到 6GB 左右后,它变得不那么活跃,似乎几乎什么也不做。

在此输入图像描述

以下是该命令(在下图中选择的一个)在 mysql 工作台中的外观。

在此输入图像描述

我正在一台具有 16GB RAM 的 Linux Mint 17.03 机器上运行 Mysql 5.7.22-0ubuntu0.16.04.1。

由于我不是高级用户,任何帮助都会有很大帮助。

更新[如 Wilson H. 建议]:

my.cnf 文件[06/05/2018 01:06]

!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/

[mysqld]
secure-file-priv = ""

[mysqld]
bulk_insert_buffer_size=1G
myisam_sort_buffer_size=8G
key_buffer_size=6G
sort_buffer_size=10M
Run Code Online (Sandbox Code Playgroud)

以下是缓冲区缓存相关变量的快照。

缓冲区和缓存相关的系统变量

我没有修改 mysql 安装中的任何其他内容。Mysqld 根据不同的表从系统可用的 16GB RAM 中占用不同的内存量。除了 mysql 之外,我不运行任何 CPU/内存密集型应用程序。

有趣的观察:对其他表的一些测试显示,随着行数的增加,时间也在增加。该趋势看起来是多项式的。

时间的多项式增加

以下统计数据是在执行上图中的最后一个 mysql 命令时捕获的(即,表“projects”的索引)。

顶部: 顶部

iostat -x: iostat-x

ulimit -a:

ulimit -a

df -h:

df-h

更新 2: 由于在“commits”表上创建索引尚未完成,我正在尝试其他表,最后我在昨晚睡觉前尝试在“project_commits”表上建立索引。令我惊讶的是,我发现只用了 18 分钟就完成了索引。

在此输入图像描述

我没有做任何额外的修改,我不明白为什么“提交”表永远不会完成。我在“提交”表上再次运行索引,看看它走了多远。

更新3:

'显示创建表提交;'

CREATE TABLE `commits` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `sha` varchar(40) DEFAULT NULL,
  `author_id` int(11) DEFAULT NULL,
  `committer_id` int(11) DEFAULT NULL,
  `project_id` int(11) DEFAULT NULL,
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `commits_ibfk_1` (`author_id`),
  KEY `commits_ibfk_2` (`committer_id`),
  KEY `commits_ibfk_3` (`project_id`)
) ENGINE=MyISAM AUTO_INCREMENT=922093754 DEFAULT CHARSET=utf8
Run Code Online (Sandbox Code Playgroud)

显示进程列表: 显示流程列表

底线:

除“commit”表外,所有表的索引均已完成(即以下命令未完成执行)。

CREATE UNIQUE INDEX `sha` ON `ghtorrent_restore`.`commits` (`sha` ASC)  COMMENT '';
Run Code Online (Sandbox Code Playgroud)

当我运行一个查询(参见下图)时,该查询从 8.91 亿行中统计出大约 19000 行,大约需要 76 秒。鉴于我的计算机配备 Core i707700HQ CPU @ 2.8Ghz x 4、16GB DDR4 Ram 并且数据库安装在 7200RPM 的 HDD 上,这个时间是否太高?76 秒是否表明“commits”表中的索引无法正常工作?请注意,此查询是在计算机启动后立即执行的,以避免缓冲区的影响。

在此输入图像描述