维基百科转储表页面链接的问题

Sim*_*ren 5 mysql size performance wikipedia dump

enwiki-latest-pagelinks.sql.gzdumps.wikimedia.org/enwiki/latest/.

我对文件进行了压缩,其未压缩大小为 37G。

表结构是这样的:

SHOW CREATE TABLE wp_dump.pagelinks;

CREATE TABLE `pagelinks` (
  `pl_from` int(8) unsigned NOT NULL DEFAULT '0',
  `pl_namespace` int(11) NOT NULL DEFAULT '0',
  `pl_title` varbinary(255) NOT NULL DEFAULT '',
  `pl_from_namespace` int(11) NOT NULL DEFAULT '0',
  UNIQUE KEY `pl_from` (`pl_from`,`pl_namespace`,`pl_title`),
  KEY `pl_namespace` (`pl_namespace`,`pl_title`,`pl_from`),
  KEY `pl_backlinks_namespace` (`pl_from_namespace`,`pl_namespace`,`pl_title`,`pl_from`)
) ENGINE=InnoDB DEFAULT CHARSET=binary
Run Code Online (Sandbox Code Playgroud)

我将该表导入到一个新的空数据库中:

mysql -D wp_dump -u root -p < enwiki-latest-pagelinks.sql
Run Code Online (Sandbox Code Playgroud)

我正在运行任务的计算机有 16G 的 RAM,并且 mysql 数据库位于 SSD 上,所以我假设尽管表的大小,导入不会花费太长时间。

但是,该任务在一天后一直在运行并且仍在运行。没有其他进程访问mysql,计算机上也没有工作负载。

数据库文件本身现在有 79G 大。

ls -lh

-rw-r----- 1 mysql mysql   65 May 11 17:40 db.opt
-rw-r----- 1 mysql mysql 8,6K May 12 07:06 pagelinks.frm
-rw-r----- 1 mysql mysql  79G May 13 16:59 pagelinks.ibd
Run Code Online (Sandbox Code Playgroud)

该表现在有超过 5 亿行。

SELECT table_name, table_rows FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'wp_dump';

+------------+------------+
| table_name | table_rows |
+------------+------------+
| pagelinks  |  520919860 |
+------------+------------+
Run Code Online (Sandbox Code Playgroud)

我想知道:

enwiki-latest-pagelinks.sql真的结束了79G大?

是否pagelinks真的含有超过500万行?

导入pagelinks表真的需要那么长时间吗?

您能否提供一些指标,即预期的表大小和行数?

更新:2017 年 5 月 14 日:

insert仍在运行; pagelinks.ibd现在文件130G;行数现在接近 7 亿

更新:2017 年 5 月 16 日:

insert仍在运行; pagelinks.ibd现在文件204G;行数现在超过 12 亿

我计算了过去两天每秒插入的行数:

行/sek = 3236

并且:在 sql 脚本中每个插入语句有数千次插入(head -41 enwiki-latest-pagelinks.sql | tail -1 | grep -o "(" | wc -l是 30471)

所以,我的后续/修改的问题:

考虑到 37G 的 sql 文件大小和表结构(如上所列),行数和 idb 文件大小是否符合预期?

rows/sek = 3236 是一个很好的值(意味着插入表需要几天时间)?

什么可能是限制速度因素/我如何加快导入速度?

  • 禁用索引(并在插入后计算它们)?
  • 优化事务(提交(脚本中没有设置)/ autocommit(现在打开))?
  • 优化变量设置(例如innodb_buffer_pool_size,现在 134217728)?

Den*_*art 6

@Sim Betren:我目前正在导入同一个表,我可以获得大约 7700 行/秒。这意味着每天大约有 600.000.000 行。可能最重要的是在 InnoDB 上获得正确的设置:

https://dba.stackexchange.com/questions/83125/mysql-any-way-to-import-a-huge-32-gb-sql-dump-faster

innodb_buffer_pool_size = 4G
innodb_log_buffer_size = 256M
innodb_log_file_size = 1G
innodb_write_io_threads = 16
innodb_flush_log_at_trx_commit = 0
Run Code Online (Sandbox Code Playgroud)

这些设置效果很好。从我阅读和尝试的内容来看,InnoDB 喜欢高内存设置。理想情况下,人们会使用 16Gb 甚至 32Gb 的机器,然后进一步增加这些设置。但是我在适度的设置中获得了 7700 行/秒,这几乎是 10 年的历史:

  • 英特尔 Q6700 四核
  • 8 Gb DDR2 内存

我将使用了 10 年的硬件与 2017 年型号的 500Gb SSD 结合使用,该 SSD 专用于这项工作并处理读取和写入。使用旧硬件的原因是 SSD 是设置中最重要的部分(因为 IOPS)。另外,通过使用较旧的硬件,我节省了一些钱。但是,硬件仅限于 8Gb 的 DDR2。我认为具有 32Gb 或 64Gb 内部存储器的较新的专用机器真的可以飞起来。

软件设置:

  • Linux 薄荷 64 位
  • 用于 Ubuntu 的 MySQL 服务器 5.7.18
  • 用于导入的 MySQL Workbench

我也在 Windows 10 上尝试过这个,两者的速度几乎相同。所以你也可以试试 Windows。

注意:我确实尝试将引擎更改为 MyISAM。MyISAM 可以非常快,大约 8000 行/秒或更多。但是由于某种原因,导入总是损坏。所以我会坚持使用 InnoDB

2017 年 6 月 17 日更新:

导入完毕。“pagelinks”表大约有 214Gb,有 12 亿行。大约 112Gb 是原始数据,102Gb 是索引。原始未压缩文件约为 37Gb。

导入耗时约 2 天 6 小时。平均速度 = 5350 行/秒。使用高端设备(巨大的内存,最好是 64Gb 或更多)和最佳设置,它可能会做得更快。但是我让它在专用机器上 24/7 全天候运行,而且我并不着急,所以 2 天似乎没问题。

2017 年 6 月 18 日更新:

还导入了“page.sql”,因为它包含连接到 ID 的名称。未压缩文件大约 5Gb,导入耗时 1 小时。这看起来很快:pagelink 文件大约 37Gb,比“page.sql”大 7 倍。然而,导入所需的时间要长 50 倍。因此,“页面链接”需要这么长时间的原因有几个:(A)可能是因为它不适合内存(B)表结构,每次插入的数据很多(C)设置。但最有可能的是记忆。

结论:尝试使用具有 32Gb 或 64Gb 内存的 PC。也许更多。并使用可以跟上该内存的 SSD,500Gb 或更多。SSD 比内存更重要,因此请先尝试。


Den*_*art 5

@西姆贝特伦:

我想打开一个全新的答案,因为我发现了一个新的解决方案。拆分文件可能是最好的答案。如另一个答案中所述,当整个模型适合内存时,InnoDB 效果最佳。当它需要交换磁盘上的东西时,延迟就开始了。pagelinks 文件是 37Gb,这对于大多数机器来说太大了,无法轻松放入内存。也许一台 1000 美元以上的内存无限的专用机器可以做到,而大多数台式机却做不到。那么你可以做什么:

  • 计划是拆分文件。首先要做的是将 SQL 结构与数据分离。
  • 可能有更好的方法来做到这一点,但我发现的一个程序是这样的: SqlDumpSplitter2

  • 该转储拆分器程序可能很旧,但它适用于页面链接。虽然它只是Windows。我只是告诉它把解压后的 37Gb 文件分成 37 个 1Gb 的块,它尽职尽责地做到了。检查数据,它似乎工作。您还可以使用 74 个 500Mb 的块。

  • 每个文件的导入每 1Gb 可能需要 10 到 20 分钟。
  • 总时间:拆分 37Gb 文件大约需要 1 到 2 小时。进口大约需要 6 到 12 小时。这很容易击败我之前给出的答案
  • 导入时,使用与上一个答案相同的大数据设置。并尝试找到具有大内存 16Gb 或 32Gb 首选的机器。

这里最重要的是:你如何分割它并不重要。无论如何,只需拆分文件即可。然后通过分别重新创建结构和数据来构建它。通过这种方式,导入时间可能会从 2 天减少到可能只有几个小时。如果有一台大型专用机器,它可能只需 1 到 6 个小时即可完成。


Ric*_*mes 3

37GB 数据 --> 79GB InnoDB 表似乎很合理......

  • 标题:2 个引号和 1 个逗号 --> 1 个字节长度
  • 整数:几个字节,加上逗号 --> 4 个字节INT(不管(...)后面的INT. 请参阅MEDIUMINT.
  • 每行 20-30 字节开销
  • BTree 的开销为 20-40%。
  • UNIQUE索引变成PRIMARY KEY和数据聚集--> 很少的开销。
  • 其他两个索引:每个索引实际上与数据大小相同。这更允许增加尺寸。

将所有这些加在一起,我预计该表将超过 120GB。因此,可能缺少一些细节。猜测:转储是每行一行INSERT,而不是更详细的每行多行INSERT

至于性能,一切取决于SELECTs。设置innodb_buffer_pool_size为 11G 左右。这对于缓存 79G 来说可能足够有效。

更多的

为了清楚起见,更改UNIQUEPRIMARY, 因为 InnoDB 确实需要 PK。

检查源数据。是按( pl_from, pl_namespace, pl_title) 顺序排列吗?如果没有,您可以在加载之前对文件进行排序吗?如果可以的话,仅此一点就可以显着提高速度。

128MB 的 buffer_pool 也严重阻碍了进展。