Elasticsearchへの大量データ登録の効率化(1)
今回は実際に並列処理による高速化を体感するため、サイズが大きめのデータを用いて並列処理を使用した場合とそうでない場合を比較してみます。
登録に使用するデータ
今回はサイズの大きなデータで、かつ無料で取得可能なWikipediaのデータを使用して大量データ登録の効率化を体験します。
データはWikipediaのタイトル、要約、リンク先が存在するWikipediaのアブストラクトデータを使用しました。本記事では2016年9月1日時点でのデータを使用しています。
データの整形
Elasticsearchに登録しやすい形に変更する処理を行います。XMLからJSON形式の変換を行います。大量の文書データを登録する際の注意点ですが、インデックス数が10000までのデータしか1バルク処理で登録できません。今回は10000インデックス単位でXMLからJSONに整形する処理を行います。
整形処理から登録する処理を行う環境構築
データの整形処理を行うための環境を構築する必要があります。
環境構築はDockerで行います。上記で示した必要な言語環境とライブラリはDockerで用意しているのでそちらをご使用ください。
[1]Wikipediaのデータを取得
Wikipediaのサイトからデータをダウンロードしてきます。注意点としてこのデータの取得には時間がかかります。著者の環境では2時間程度かかりました。
cd {your download folder}/elastic-search-docker_parallel/python/Data/split_data/
wget https://dumps.wikimedia.org/jawiki/latest/jawiki-latest-abstract.xml
[2]Vagrantを起動する
"Vagrantfile"のIPアドレスを環境に応じて設定してください。他にVagrantを使用している場合は 同一のIPアドレスにならないようにしてください。
例:192.168.33.21
confing.vm.network "private_network", ip {your ip address}
取得したコードのディレクトリに移動し下記でvagrantを起動してください。
cd {your download folder}/elastic-search-docker_parallel
vagrant up
下記のコマンドを使用してvagrantで作成した環境に入ってください。
vagrant ssh
前回の記事で紹介したDocker環境の構築方法に沿ってDocker環境を構築してください。既にDockerを起動できる環境をVagrant上で構築済みの方は必要ありません。
[3]Dockerコンテナイメージの取得
今回の記事の環境が再現されたDockerイメージを取得します。注意点としてDockerイメージの取得には時間がかかります。
docker pull masayaresearch/elasticsearch_japanese_parallel
下記のコマンドでDockerイメージの情報を取得できます。
docker images
下記のような情報が取得できるので"IMAGE ID"をメモしてください。
REPOSITORY TAG IMAGE ID CREATED SIZE masayaresearch/elasticsearch_japanese_parallel latest 読者の環境に依存 読者の環境に依存 7.092GB
[4]Elasticsearchの動作環境
実際に動作させるにはコンテナに入る必要があります。
Dockerコンテナに入るコマンドは下記です。先ほど取得したWikipediaのデータをコンテナと連携させるため、-vオプションでホストとコンテナを連携させます。
docker run -v /home/vagrant/elastic-search-docker_parallel/python:/usr/share/elasticsearch/python -it {先ほどメモしたIMAGE ID} bash
これで整形処理の環境が設定されている環境へアクセスできました。
下記で整形処理を行うディレクトリに移動します。連携したフォルダに権限がないので権限を与えておきます。sudoのパスワードは"e_pass"です。
sudo chmod -R 777 /usr/share/elasticsearch/python/Data cd python
データの整形処理Codeについて
整形処理を行っている重要な部分のみを抜粋しました。XML形式のデータを解析しやすくするため"xml.etree.ElementTree"を使用しています。
self.xml_data = xml.etree.ElementTree.parse(self.wikipedia_abstract_xml).getroot()
XMLデータの解析処理部分です。インデックスのサイズが10000までしかバルク処理で登録できないので10000以上になると別のJSONファイルに分けて処理するようにしています。
index_count = 0
file_index_count = 1
self.extract_dict_array = ["title", "abstract", "url"]
for doc in self.xml_data:
for extract_data in doc:
self.judge_remake_data(extract_data, index_count)
self.__output_json()
self.json_data = {}
index_count = index_count + 1
if index_count % 10000 == 0:
before_file_index_count = file_index_count - 1
self.wikipedia_abstract_json =self.wikipedia_abstract_json.replace(str(before_file_index_count) + ".json", str(file_index_count) + ".json")
print(self.wikipedia_abstract_json)
file_index_count = file_index_count + 1
解析して得られた文書データのタグが"title"、"abstract"、"url"のいずれかの場合に、JSON出力用の辞書オブジェクトのデータを更新しています。"title"部分に"Wikipedia: "と含まれているデータなので置き換え処理をしています。
if extract_data.tag in self.extract_dict_array:
# replace method for title extract
if extract_data.text is not None:
self.index_json.update({ "index" : { "_index" : "wikipedia", "_type" : "contents", "_id" : str(index_count) } })
replace_text = extract_data.text.replace("Wikipedia: ", "")
self.json_data.update({extract_data.tag: replace_text})
else:
self.index_json.update({ "index" : { "_index" : "wikipedia", "_type" : "contents", "_id" : str(index_count) } })
self.json_data.update({extract_data.tag: extract_data.text})
下記で実行します。
mv /usr/share/elasticsearch/python/Data/split_data/jawiki-latest-abstract.xml /usr/share/elasticsearch/python/Data/split_data/jawiki-20160901-abstract.xml python execute_wiki_pedia_xml_to_json.py
作成されたファイルは下記のようになります。
/usr/share/elasticsearch/python/Data/split_data/jawiki-20160901-abstract0.json : /usr/share/elasticsearch/python/Data/split_data/jawiki-20160901-abstract102.json
標準5~15MBのサイズでバルク処理が行えますが、ドキュメントのサイズによっては確保できるメモリの量に影響が起きて速度が遅くなる可能性があります。そこで高速化のために圧縮処理をかけてサイズを減らしておきます。
gzip /usr/share/elasticsearch/python/Data/split_data/jawiki-20160901-abstract*.json
Gzip形式の圧縮されたファイルが作成されます。
elasticsearch.ymlの設定ファイルも圧縮されたファイルを扱えるように下記の追記を行っています。"/etc/elasticsearch/elasticsearch.yml"の80行から90行で下記の記述を確認できます。
# ----------------------------------- Compress ----------------------------------- http.compression: true
