RailsでRDBデータをElasticsearchに超高速で全件登録したい気持ち(未検証)

Rails何もわからない民。RDBのデータ件数が猛烈に多く、Elasticsearchへの全件登録にXX時間かかるので、どうにかしようとしている。以下は妄想メモ。そのうち検証する。

現状から書き換えてみる

これがテーブル全件登録。現状これでXX時間かかっている。 __elasticsearch__elasticsearch-rails というgemがモデルクラスに生やしてるオブジェクト。ここに import とか index_document などのメソッドが生えている。 import の実装は https://github.com/elastic/elasticsearch-rails/blob/master/elasticsearch-model/lib/elasticsearch/model/importing.rb#L140-L185

Hoge.__elasticsearch__.import(index: new_index_name)

このような書き換えができる。一件登録の __elasticsearch__.index_document というメソッドが存在してる。 index_document の実装は https://github.com/elastic/elasticsearch-rails/blob/master/elasticsearch-model/lib/elasticsearch/model/indexing.rb#L370-L378

Hoge.find_each do |o|
    o.__elasticsearch__.index_document(index: new_index_name)
end

find_eachfind_in_batch をラップしたメソッドで、このように書き換えできる。

Hoge.find_in_batch do |records|
    records.each do |o|
        o.__elasticsearch__.index_document(index: new_index_name)
    end
end

find_in_batch でレコードを配列として持ってきたことで、Parallel に渡せるようになる。Parallel はマルチスレッド処理を簡易に使えるようにするgem。in_threads は並列数。あまり無茶するとEC2インスタンスが爆散するので控えめにする。

Hoge.find_in_batch do |records|
    Parallel.each(records, in_threads: 4) do |o|
        ActiveRecord::Base.connection_pool.with_connection do
            o.__elasticsearch__.index_document(index: new_index_name)
        end
    end
end

ところで Datadog でインポート中のメモリの動きを見ていると、スワップに手を付けそうになっている。ActiveRecord がメモリにクエリキャッシュを溜めるのをOFFってみる。これが効くかわからないが。

Hoge.uncached do
    Hoge.find_in_batch do |records|
        Parallel.each(records, in_threads: 4) do |o|
            ActiveRecord::Base.connection_pool.with_connection do
                o.__elasticsearch__.index_document(index: new_index_name)
            end
        end
    end
end

という妄想を書き散らしたが、ほんとに効くのかわからない。そもそも動くのか不明。

こうなってほしいな

参考文書

そもそもRailsバッチ処理の最適化ってどうやんの、の概観。

blog.toshimaru.net

elasticsearch-rails と使い方のサンプル。

github.com qiita.com

find_eachfind_in_batch

qiita.com daido.hatenablog.jp

Parallel と使い方サンプル。

github.com www.bokukoko.info

ActiveRecord::QueryCache::uncached と使い方サンプル。

api.rubyonrails.org qiita.com

Sidekiqがメモリ蕩尽するみたいな文脈でも、uncached しろって指南があった。

github.com

Elasticsearch のバルクAPI

www.elastic.co qiita.com