ElasticSearch、Logstash、MySQL:如何加速大型导入?

ElasticSearch, Logstash, MySQL: how do I speed up a large import?

我正在尝试将大型(约 3000 万行)MySQL 数据库导入 ElasticSearch。酷酷的,有一个 logstash 工具看起来像是为这类事情而构建的;它的 JDBC 插件可以让我直接连接到数据库并快速收集行。

但是!当我尝试它时,它以 java.lang.OutOfMemoryError 轰炸。好的。它可能试图批量处理太多行或其他内容。所以我将 jdbc_fetch_size => 1000 添加到我的配置中。没有骰子,仍然没有记忆。好的,也许那个选项不起作用,或者不符合我的想法?

所以我尝试将 jdbc_paging_enabled => truejdbc_page_size => 10000 添加到我的配置中。成功!它开始以 10k 为单位向我的索引中添加行。

但是速度变慢了。一开始我是 运行宁 100k rows/minute;然而,当我达到 2M 行时,我可能只有它的十分之一。毫不奇怪;我很确定这是在使用 LIMIT 和 OFFSET,并且在查询中使用巨大的 OFFSET 真的很慢,所以我在这里处理 O(n^2) 的事情。

我真的很想 运行 整个大查询并让游标遍历结果集,但由于某种原因它看起来不起作用。如果我能更好地控制查询,我可以将 LIMIT/OFFSET 的东西改成 WHERE id BETWEEN val1 AND val2 之类的东西,但我看不出我可以从哪里开始这样做。

关于如何不崩溃,但仍然运行以合理的速度有什么建议吗?

好的!在搜索 "Memory" 的 logstash-input-jdbc github 页面的问题后,我发现 this revelation:

It seems that an additional parameter ?useCursorFetch=true needs to be added to the connection string of mysql 5.x.

事实证明,由于某些原因,MySQL JDBC 客户端在默认情况下不使用游标来获取行,并且 logstash 客户端不会警告您它不能使用游标遍历结果集,即使您因为某些其他原因设置了 jdbc_fetch_size

当然,了解这一点的明显方法是仔细阅读 the MySQL Connector/J documentation,其中确实提到游标默认关闭,但没有说明原因。

无论如何,我将 useCursorFetch=true 添加到连接字符串,将 jdbc_query_paging 踢到路边,并在 2.5 小时内将 2600 万行导入到我的索引中,这是在一台具有 8G 内存的老旧 Macbook Pro 上。

感谢 github 用户 axhiao 的有用评论!