维基百科转储问题 table 页面链接
Issues with wikipedia dump table pagelinks
我从 dumps.wikimedia.org/enwiki/latest/
下载了 enwiki-latest-pagelinks.sql.gz
转储。
我把文件打包了,解压后大小是37G。
table结构是这样的:
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
我将 table 导入到一个新的空数据库中:
mysql -D wp_dump -u root -p < enwiki-latest-pagelinks.sql
我所在的计算机 运行 有 16G RAM 并且 mysql 数据库位于 SSD 上,所以我假设尽管 table 的大小导入不会花费太长时间。
但是,任务 运行 一天多了,仍然 运行。没有其他进程访问 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
table 现在有超过 5 亿行。
SELECT table_name, table_rows FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'wp_dump';
+------------+------------+
| table_name | table_rows |
+------------+------------+
| pagelinks | 520919860 |
+------------+------------+
我在想:
enwiki-latest-pagelinks.sql
真的超过79G大吗?
pagelinks
真的包含超过 5 亿行吗?
导入 pagelinks
table 真的需要那么长时间吗?
能否提供一些指标,如预期的 table 大小和行数,好吗?
更新:2017 年 5 月 14 日:
insert
还是运行; pagelinks.ibd
现在文件130G;行数现在将近 7 亿
更新:2017 年 5 月 16 日:
insert
还是运行; pagelinks.ibd
现在文件204G;行数现在超过 12 亿
我计算了过去两天每秒插入的行数:
rows/sek = 3236
并且:sql 脚本中每个插入语句有数千次插入(head -41 enwiki-latest-pagelinks.sql | tail -1 | grep -o "(" | wc -l
是 30471)
所以,我的后续/修改问题:
给定 sql 37G 文件大小和 table 结构(如上所列),行数和 idb 文件大小是否符合预期?
rows/sek = 3236 是一个好的值吗(意味着需要几天时间才能插入 table)?
限制速度因素可能是什么/我怎样才能加快导入速度?
- 禁用索引(并在插入后计算它们)?
- 优化交易(提交(脚本中未设置任何内容)/
autocommit
(现在开启))?
- 优化变量设置(例如
innodb_buffer_pool_size
,现在是134217728)?
37GB 数据 --> 79GB InnoDB table 似乎合理...
- 标题:2 个引号和 1 个逗号 --> 1 个字节的长度
- Ints:几个字节,加上逗号 --> 4 个字节用于
INT
(不管 [=10= 之后的 (...)
)。参见 MEDIUMINT
。
- 每行 20-30 字节开销
- BTrees 的开销为 20-40%。
UNIQUE
索引变成 PRIMARY KEY
并且有数据集群 --> 开销很小。
- 其他两个索引:每个索引实际上都与数据大小相同。这更多允许增加尺寸。
加在一起,我预计 table 会超过 120GB。因此,可能缺少一些细节。一个猜测:转储是每个 INSERT
一行,而不是不那么冗长的 many-rows-per-INSERT
.
至于性能,全看SELECTs
。将 innodb_buffer_pool_size
设置为 11G 左右。这可能足够有效地缓存 79G。
更多
为了清晰起见,将 UNIQUE
更改为 PRIMARY
,因为 InnoDB 确实需要 PK。
检查源数据。是(pl_from
,pl_namespace
,pl_title
)顺序吗?如果没有,您可以在加载前对文件进行排序吗?如果可以,仅此一项就可以显着提高速度。
buffer_pool 的 128MB 也严重阻碍了进度。
@Sim Betren:我目前正在导入相同的table,我可以得到大约7700 rows/s。这意味着每天大约有 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
这些设置效果很好。根据我的阅读和尝试,InnoDB 喜欢高内存设置。理想情况下,可以使用 16Gb 甚至 32Gb 的机器,然后进一步增加这些设置。但是我在适度的设置下得到了 7700 rows/s,这已经快 10 年了:
- 英特尔 Q6700 四核
- 8 Gb DDR2 内存
我将那个 10 年前的硬件与 2017 型号的 500Gb SSD 组合在一起,它专用于这项工作并处理读取和写入。使用旧硬件的原因是 SSD 是设置中最重要的部分(因为 IOPS)。另外,通过使用旧硬件,我节省了一些钱。但是,硬件仅限于 8Gb 的 DDR2。我认为具有 32Gb 或 64Gb 内存的较新的专用机器真的可以飞起来。
软件设置:
- Linux 薄荷 64 位
- MySQL Ubuntu
服务器 5.7.18
- MySQL Workbench 用于导入
我也在 Windows 10 上尝试过,两者的速度几乎相同。所以你也可以试试 Windows。
注意:我确实尝试将引擎更改为 MyISAM。 MyISAM 可以非常快,也大约 8000 rows/sec 或更多。但是由于某种原因,导入总是被损坏。所以我会坚持使用 InnoDB
2017 年 6 月 17 日更新:
已完成导入。 table "pagelinks" 大约有 214Gb,有 12 亿行。大约 112Gb 是原始数据,102Gb 是索引。原始未压缩文件大约为 37Gb。
导入大约用了 2 天 6 小时。平均速度 = 5350 rows/s 秒。使用高端设备(大内存,最好是 64Gb 或更多)和最佳设置,它可能会更快地完成。但我让它 运行 在专用机器上 24/7 并且我并不着急,所以 2 天似乎没问题。
2017 年 6 月 18 日更新:
还导入了 "page.sql",因为它包含与 ID 相关的名称。解压文件约5Gb,导入耗时1小时。这看起来很快:页面链接文件大约 37Gb,比 "page.sql" 大 7 倍。但导入时间要长 50 倍。因此,"pagelinks" 花费这么长时间的原因有几个:(A) 可能是因为它不适合内存 (B) table 结构,每次插入很多数据 (C) 设置。但最有可能的是记忆。
结论:尝试获得具有 32Gb 或 64Gb 内存的 PC。也许更多。并使用能够跟上该内存(500Gb 或更多)的 SSD。 SSD 比内存更重要,所以先试试。
@Sim Betren:
我想打开一个全新的答案,因为我发现了一个新的解决方案。拆分文件可能是最好的答案。正如另一个答案中所讨论的,当整个模型适合内存时,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 小时内完成。
我从 dumps.wikimedia.org/enwiki/latest/
下载了 enwiki-latest-pagelinks.sql.gz
转储。
我把文件打包了,解压后大小是37G。
table结构是这样的:
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
我将 table 导入到一个新的空数据库中:
mysql -D wp_dump -u root -p < enwiki-latest-pagelinks.sql
我所在的计算机 运行 有 16G RAM 并且 mysql 数据库位于 SSD 上,所以我假设尽管 table 的大小导入不会花费太长时间。
但是,任务 运行 一天多了,仍然 运行。没有其他进程访问 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
table 现在有超过 5 亿行。
SELECT table_name, table_rows FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'wp_dump';
+------------+------------+
| table_name | table_rows |
+------------+------------+
| pagelinks | 520919860 |
+------------+------------+
我在想:
enwiki-latest-pagelinks.sql
真的超过79G大吗?
pagelinks
真的包含超过 5 亿行吗?
导入 pagelinks
table 真的需要那么长时间吗?
能否提供一些指标,如预期的 table 大小和行数,好吗?
更新:2017 年 5 月 14 日:
insert
还是运行; pagelinks.ibd
现在文件130G;行数现在将近 7 亿
更新:2017 年 5 月 16 日:
insert
还是运行; pagelinks.ibd
现在文件204G;行数现在超过 12 亿
我计算了过去两天每秒插入的行数:
rows/sek = 3236
并且:sql 脚本中每个插入语句有数千次插入(head -41 enwiki-latest-pagelinks.sql | tail -1 | grep -o "(" | wc -l
是 30471)
所以,我的后续/修改问题:
给定 sql 37G 文件大小和 table 结构(如上所列),行数和 idb 文件大小是否符合预期?
rows/sek = 3236 是一个好的值吗(意味着需要几天时间才能插入 table)?
限制速度因素可能是什么/我怎样才能加快导入速度?
- 禁用索引(并在插入后计算它们)?
- 优化交易(提交(脚本中未设置任何内容)/
autocommit
(现在开启))? - 优化变量设置(例如
innodb_buffer_pool_size
,现在是134217728)?
37GB 数据 --> 79GB InnoDB table 似乎合理...
- 标题:2 个引号和 1 个逗号 --> 1 个字节的长度
- Ints:几个字节,加上逗号 --> 4 个字节用于
INT
(不管 [=10= 之后的(...)
)。参见MEDIUMINT
。 - 每行 20-30 字节开销
- BTrees 的开销为 20-40%。
UNIQUE
索引变成PRIMARY KEY
并且有数据集群 --> 开销很小。- 其他两个索引:每个索引实际上都与数据大小相同。这更多允许增加尺寸。
加在一起,我预计 table 会超过 120GB。因此,可能缺少一些细节。一个猜测:转储是每个 INSERT
一行,而不是不那么冗长的 many-rows-per-INSERT
.
至于性能,全看SELECTs
。将 innodb_buffer_pool_size
设置为 11G 左右。这可能足够有效地缓存 79G。
更多
为了清晰起见,将 UNIQUE
更改为 PRIMARY
,因为 InnoDB 确实需要 PK。
检查源数据。是(pl_from
,pl_namespace
,pl_title
)顺序吗?如果没有,您可以在加载前对文件进行排序吗?如果可以,仅此一项就可以显着提高速度。
buffer_pool 的 128MB 也严重阻碍了进度。
@Sim Betren:我目前正在导入相同的table,我可以得到大约7700 rows/s。这意味着每天大约有 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
这些设置效果很好。根据我的阅读和尝试,InnoDB 喜欢高内存设置。理想情况下,可以使用 16Gb 甚至 32Gb 的机器,然后进一步增加这些设置。但是我在适度的设置下得到了 7700 rows/s,这已经快 10 年了:
- 英特尔 Q6700 四核
- 8 Gb DDR2 内存
我将那个 10 年前的硬件与 2017 型号的 500Gb SSD 组合在一起,它专用于这项工作并处理读取和写入。使用旧硬件的原因是 SSD 是设置中最重要的部分(因为 IOPS)。另外,通过使用旧硬件,我节省了一些钱。但是,硬件仅限于 8Gb 的 DDR2。我认为具有 32Gb 或 64Gb 内存的较新的专用机器真的可以飞起来。
软件设置:
- Linux 薄荷 64 位
- MySQL Ubuntu 服务器 5.7.18
- MySQL Workbench 用于导入
我也在 Windows 10 上尝试过,两者的速度几乎相同。所以你也可以试试 Windows。
注意:我确实尝试将引擎更改为 MyISAM。 MyISAM 可以非常快,也大约 8000 rows/sec 或更多。但是由于某种原因,导入总是被损坏。所以我会坚持使用 InnoDB
2017 年 6 月 17 日更新:
已完成导入。 table "pagelinks" 大约有 214Gb,有 12 亿行。大约 112Gb 是原始数据,102Gb 是索引。原始未压缩文件大约为 37Gb。
导入大约用了 2 天 6 小时。平均速度 = 5350 rows/s 秒。使用高端设备(大内存,最好是 64Gb 或更多)和最佳设置,它可能会更快地完成。但我让它 运行 在专用机器上 24/7 并且我并不着急,所以 2 天似乎没问题。
2017 年 6 月 18 日更新:
还导入了 "page.sql",因为它包含与 ID 相关的名称。解压文件约5Gb,导入耗时1小时。这看起来很快:页面链接文件大约 37Gb,比 "page.sql" 大 7 倍。但导入时间要长 50 倍。因此,"pagelinks" 花费这么长时间的原因有几个:(A) 可能是因为它不适合内存 (B) table 结构,每次插入很多数据 (C) 设置。但最有可能的是记忆。
结论:尝试获得具有 32Gb 或 64Gb 内存的 PC。也许更多。并使用能够跟上该内存(500Gb 或更多)的 SSD。 SSD 比内存更重要,所以先试试。
@Sim Betren:
我想打开一个全新的答案,因为我发现了一个新的解决方案。拆分文件可能是最好的答案。正如另一个答案中所讨论的,当整个模型适合内存时,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 小时内完成。