83億レコードを移行し、日々2,500万レコードのアクセスログをBigQueryに記録している話(インフラ編)

こんにちは。
インフラエンジニアの村上です。

マネーフォワードのインフラチームは、サービスに関わるインフラから、自社の作業環境、開発環境、さらにはサービスのインフラの中でも物理的なものからOS・ミドルウェア・アプリケーションのメンテナンス・ビルド・リリース・運用まで幅広く関与しています。

今回はGoogle Cloud PlatformのBigQueryを活用してアクセスログの分析環境を構築した時の話を紹介します。

bigquery+embulk

この記事に書かれる事

  • データ分析基盤としてBigQueryを使用した話と
  • データ量を例示しながら使用を開始した時のトラブルシュートとパフォーマンスについて紹介する。
  • データ移行のコツもうまく含めながら書いていく。
     

BigQueryを採用した訳

マネーフォワードの家計簿は350万人以上のお客様に利用いただき、
アクセスログは日々2.500万件程度増えております。
サービス開始からアクセスログの件数を追いかけると

件数
2013 150,203,996 件 (1.5億件)
2014 827,362,575 件 (8.2億件)
2015 3,684,027,293 件 (36.8億件)
2016 3,666,660,640 件 (36.6億件 6月末時点)
合計 8,328,254,504件 (83.2億件)

のデータをMySQL上に保管していました。
ユーザーの皆様により満足頂ける様に、データ分析を元にしたサービス改善にも取り組んでおりましたが、
数億レコードに対してデータ分析を行う上でMySQLだけだと辛い。との事で、データ分析基盤を構築する事になりました。
最近活用事例も多く、予算見積もりした時も低コストだったBigQueryを試してみる事になりました。
 

予算を決める

社内で新しい事を始める時には予算を決めて、その枠組でまず頑張ってみる事にしています。
今回のスタート時の予算はまずは5万円 + GCPのFreeTrial + クーポン(3万円分) で始める事にしました。

アクセスログに関しては以下の様に見積もりをしています。

データ量を試算する

見積もりの為、BigQueryに保存した時のデータ量を以下の流れで求めます。

  1. 数カ月分BigQueryに入れてみてサイズ比較を行う
  2. MySQL上のデータサイズと比率を元に、BigQueryに全件入れた時のデータサイズを求める。

数カ月分BigQueryに入れてみてサイズ比較を行う

月    DB  BigQuery 比率
2013/09 1.0GB 2.5GB  2.5 
2013/10 2.0GB 4.8GB  2.4 
2013/11 2.3GB 5.1GB  2.3 
2013/12 2.8GB 6.5GB  2.3 

MySQLで圧縮をかけている、いないで比率は変わると思われます。
弊社環境では圧縮していました。

MySQL上の全データサイズを求める

  • 過去分 500 GB
  • 直近3ヶ月のデータ量 130 GB(クエリコスト計算に使う)

BigQuery上の予想データ量を求める

大体 2.4 倍ぐらいになるので、BigQuery上では
500 GB * 2.4 = 1.2 TB になると予想。

コストを試算する

保存コスト

BigQueryは長期保存の料金というのがあるので、
インポート直後と、3ヶ月経過後で金額を計算しておきます。

直近(インポート直後):
$0.02 / GB / 月 * 1200GB * 110円 = 2640円

三ヶ月経過後は割引:
$0.01 / GB / 月 * 1200GB * 110円= 1320円

TB単位でいれてこの値段なので保管に関してものすごく安いですね。

クエリコスト

直近1ヶ月のクエリ対象テーブルのサイズを月130GB になると仮定し、
クエリコストも月 1TB までは無料を加味する。

直近1ヶ月を 100 回:
130GB * 100回 / 1000 = 13TB
$5/TB * (13TB – 1TB) * 110円 = 6600円

直近1ヶ月を 1000 回:
130GB * 1000回 / 1000 = 130TB
$5/TB * (130TB – 1TB) * 110円 = 70950円

ストリーミングコスト

バルクでいれるのでストリーミングコストはなし。

トータルコストを算出する

保存:1320円~2640円
クエリ:6600円~70950円
トータル:7920円~73590円

となりました。この数値を元に社内では\30,000~\50,000目安で活用してみよう。という事になりました。

注:
– 数字は適宜適当に丸めてある
– 1$ = 110円で計算

最新のGCPのPricingについては[Google Cloud Platform Documentation /BigQuery/料金]を参照ください。
 

過去データ移行

BigQueryを安くかつ効率よく利用する為に、弊社はTreasure Dataが提供する[embulk]を利用してデータをBigQueryに入れる事にしました。
過去分・日次のデータ投入もEmbulkを使用しています。ストリーミングインサートはお金がかかるので避ける事で費用を節約しています。

データ移行の単位

データの移行にあたってはEmbulkの config.yml.liquid
・月単位
・週単位
等データ量に合わせて作成し、これらをScreenを貼った上でfor文でぐるぐる実行しています。
EmbulkはGZIPオプションをつけるとCPUを結構使います。
ので同一サーバー上で複数のEmbulkは実行せずにシーケンシャルに処理を実行しました、
今回は1台で実行した結果、全データ移行に2~3週間かかっています。(トラブルシュートも含む)

最初は月単位で移行していたのですが、途中からエラーが出て進まなくなったので
週単位程度に config.yml.liquid を分けて実行する様にした所安定して移行が終わりました。

移行にかかった時間

月単位の移行データ量(MB) on MySQL(圧縮済) と、記録を残してる範囲での処理時間と
対象期間の分割は以下になります。

ログ MySQL上のサイズ(MB) 件数 メモ
access_log_201312 2925 37,898,506件 (3.7千万件)
access_log_201401 3743 46,116,223件 (4.6千万件) 89分
access_log_201402 3994 49,186,018件 (4.9千万件
~略~
access_log_201502 7221 120,993,418件 (1.2億件)
access_log_201503 8004 134,946,137件 (1.3億件) 226分
access_log_201504 8752 154,994,175件 (1.5億件) 276分  ← ここまでは月単位で行けた。
access_log_201505 10339 178,718,485件 (1.7億件) ← ここからは1カ月6分割して行けた。
~略~
access_log_201604 33559 564,732,259件 (5.6億件)
access_log_201605 未計測 627,698,533件 (6.2億件) 大体5時間×6回=30時間くらい
access_log_201606 未計測 640,219,668件 (6.4億件) 大体5時間×6回=30時間くらい| 

日次運用

運用スクリプト

日次ではJenkinsから朝6時にShellを呼び出して、Embulkを使ってBigQueryにデータを入れています。
大体1日2000万件~2500万件のレコードを1時間強の時間で処理を終えています。
処理フローは以下です。
– 時刻になったらJenkinsが起動する
– 最新版のEmbulkConfig等を配布する
– Scriptを実行する
– 当日用のconfig.yml.liquidを生成する
– embulkを実行する
– 終了時にSlackへ通知する


#!/bin/sh
# Fail on unset variables and command errors
set -ue -o pipefail
# Prevent commands misbehaving due to locale differences
export LC_ALL=C
export base_dir=$(cd $(dirname $0) && pwd)

# embulkがERROR終了した時は、EXITしてリターンコードを受け取る事が出来ないケースがあるので、trap EXITでcatchする様にした。
# exit_statusはデフォルト9にして、正常終了時だけ0にUpdateしてからtrapに辿り着く様にした。
export exit_status=9
trap "clean_config && notice_slack \"BigQuery data import finish.\"" EXIT ERR

# function
function clean_config() {
  cd ${base_dir}/../
  find . -name config.yml.liquid | xargs rm -f
}

function notice_slack() {
  ~~略~~
}

function execute_embulk() {
  target=$1
  cd ${base_dir}/../${target}
  echo "${target} import start"
  if [ -e "config.yml.liquid" ]; then rm -f config.yml.liquid ; fi
  bundle exec ruby gen_config.rb
  embulk run config.yml.liquid -b ../vendor/bundle
  echo "${target} import finish"
}

# main
cd ${base_dir}/../
execute_embulk access_log
export exit_status=$?

in:
  type: mysql
  host: {{ env.LOG_DB_HOST }}
  user: {{ env.LOG_DB_USERNAME }}
  password: {{ env.LOG_DB_PASSWORD }}
  database: log_production
  query: |
    SELECT hoge,fuga,accessed_at
    FROM access_log
    FORCE INDEX (index_access_log_on_accessed_at)
    WHERE accessed_at >= <%= from_date %> and accessed_at < <%= to_date %>
filters:
  - type: add_mf_channel
  - type: add_time
    to_column:
      name: accessed_at_jst
      type: timestamp
    from_column:
      name: accessed_at
  - type: eval
    eval_columns:
      - accessed_at_jst: value + (9 * 60 * 60)
out:
  type: bigquery
  mode: append
  auth_method: json_key
  json_keyfile:
    content: |
      {{ env.BIGQUERY_JSON_KEY }}
  dataset: {{ env.envname | append: "_access_log" }}
  table: access_log_<%= table_timestamp %>
  auto_create_table: true
  schema_file: ./schema.json
  source_format: NEWLINE_DELIMITED_JSON
  compression: GZIP
  timeout_sec: 3000
  open_timeout_sec: 3000

データ量と処理時間

最近の処理時間は以下の様な感じです。
件数辺りの処理時間も日によってかかる時間は微妙に前後している様ですが、
朝6時から起動し、おおむね始業時間位には終わっています。

日付 件数 処理時間
2016/07/25 27,525,163件 (2.7千万件) 3時間3分
2016/07/26 23,684,254件 (2.3千万件) 3時間39分
2016/07/27 25,209,016件 (2.5千万件) 3時間18分
2016/07/28 22,088,613件 (2.2千万件) 3時間17分
2016/07/29 20,940,223件 (2.1千万件) 3時間5分
2016/07/30 20,541,243件 (2.0千万件) 2時間56分
2016/07/31 22,535,411件 (2.2千万件) 2時間57分

サーバー側のリソースモニタ

CPU

2コアのマシンで実行していますが、コアはそこそこ活用して動いています。
Out句のGZIPオプションでGZIP化している処理がCPUを使う様です。GZIPを外すとCPUはかなり落ち着きますが、
BigQueryに転送する時の転送スピードが遅くなります。

cpu-monitor

MEM

12GBのマシンの表示です。一時的にメモリは結構な量を使っている様です。

mem

Network Trafic

eth0 は 100MのインターネットLAN、eth1は1GのインターナルなLANです。
BigQueryに書き込みに行くところで、一時的に15M~20M程使っています。

trafic
 

トラブルシュート

さて、順調に行ったかの様に見えるデータ移行ですが、幾つかのエラーに遭遇したのでここに記録します。
使用しているEmbulkのバージョンはEmbulk v0.8.9 になります。

2013年分のログは一括でインポート出来て非常に順調だったのですが、2014年分を丸っと入れようとすると、以下のエラーが出ました。

データ投入がTimeOutする

原因と対策

以下にエラーログと正常なログを載せましたが、どうやらBigQueryにCommitしようとしたタイミングで期限切れ(execution expired) エラーが出ています。BigQueryにデータを入れる時に、1トランザクションで一定の処理時間を越えるとトランザクションがタイムアウトしてしまう様です。

Out句に

  timeout_sec: 3000
  open_timeout_sec: 3000

を足す事で対応しました。
また、データ量が増えるとこれでも60分で落ちる様になるので対象期間を絞る事で発生しなくなりました。

サンプルエラーログ

2016-06-07 23:51:59.727 +0900 [INFO] (0001:transaction): embulk-output-bigquery: delete /tmp/embulk_output_bigquery_20160607-19653-1oshdi9.19653.12830.jsonl.gz
2016-06-07 23:52:00.137 +0900 [INFO] (0001:transaction): embulk-output-bigquery: delete /tmp/embulk_output_bigquery_20160607-19653-1oshdi9.19653.12832.jsonl.gz
2016-06-07 23:52:00.138 +0900 [INFO] (0001:transaction): embulk-output-bigquery: delete /tmp/embulk_output_bigquery_20160607-19653-1oshdi9.19653.12834.jsonl.gz
org.embulk.exec.PartialExecutionException: org.jruby.exceptions.RaiseException: (TransmissionError) execution expired
        at org.embulk.exec.BulkLoader$LoaderState.buildPartialExecuteException(org/embulk/exec/BulkLoader.java:363)
        at org.embulk.exec.BulkLoader.doRun(org/embulk/exec/BulkLoader.java:572)
        at org.embulk.exec.BulkLoader.access$000(org/embulk/exec/BulkLoader.java:33)
        at org.embulk.exec.BulkLoader$1.run(org/embulk/exec/BulkLoader.java:374)
        at org.embulk.exec.BulkLoader$1.run(org/embulk/exec/BulkLoader.java:370)
        at org.embulk.spi.Exec.doWith(org/embulk/spi/Exec.java:25)
        at org.embulk.exec.BulkLoader.run(org/embulk/exec/BulkLoader.java:370)
        at org.embulk.EmbulkEmbed.run(org/embulk/EmbulkEmbed.java:180)
        at java.lang.reflect.Method.invoke(java/lang/reflect/Method.java:606)
        at RUBY.run(uri:classloader:/embulk/runner.rb:84)
        at RUBY.run(uri:classloader:/embulk/command/embulk_run.rb:306)
        at RUBY.<top>(uri:classloader:/embulk/command/embulk_main.rb:2)
        at org.jruby.RubyKernel.require(org/jruby/RubyKernel.java:937)
        at opt.bin.embulk.embulk.command.embulk_bundle.<top>(file:/opt/bin/embulk!/embulk/command/embulk_bundle.rb:30)
        at java.lang.invoke.MethodHandle.invokeWithArguments(java/lang/invoke/MethodHandle.java:599)
        at org.embulk.cli.Main.main(org/embulk/cli/Main.java:23)
Caused by: org.jruby.exceptions.RaiseException: (TransmissionError) execution expired
        at RUBY.error(/hoge/access_log_loader/vendor/bundle/jruby/2.2.0/gems/google-api-client-0.9.6/lib/google/apis/core/http_command.rb:256)
        at RUBY.execute_once(/hoge/access_log_loader/vendor/bundle/jruby/2.2.0/gems/google-api-client-0.9.6/lib/google/apis/core/upload.rb:284)
        at RUBY.block in execute(/hoge/access_log_loader/vendor/bundle/jruby/2.2.0/gems/google-api-client-0.9.6/lib/google/apis/core/http_command.rb:107)
        at RUBY.block in retriable(/hoge/access_log_loader/vendor/bundle/jruby/2.2.0/gems/retriable-2.1.0/lib/retriable.rb:54)
        at org.jruby.RubyFixnum.times(org/jruby/RubyFixnum.java:302)
        at RUBY.retriable(/hoge/access_log_loader/vendor/bundle/jruby/2.2.0/gems/retriable-2.1.0/lib/retriable.rb:48)
        at RUBY.block in execute(/hoge/access_log_loader/vendor/bundle/jruby/2.2.0/gems/google-api-client-0.9.6/lib/google/apis/core/http_command.rb:104)
        at RUBY.block in retriable(/hoge/access_log_loader/vendor/bundle/jruby/2.2.0/gems/retriable-2.1.0/lib/retriable.rb:54)
        at org.jruby.RubyFixnum.times(org/jruby/RubyFixnum.java:302)
        at RUBY.retriable(/hoge/access_log_loader/vendor/bundle/jruby/2.2.0/gems/retriable-2.1.0/lib/retriable.rb:48)
        at RUBY.execute(/hoge/access_log_loader/vendor/bundle/jruby/2.2.0/gems/google-api-client-0.9.6/lib/google/apis/core/http_command.rb:96)
        at RUBY.execute_or_queue_command(/hoge/access_log_loader/vendor/bundle/jruby/2.2.0/gems/google-api-client-0.9.6/lib/google/apis/core/base_service.rb:345)
        at RUBY.insert_job(/hoge/access_log_loader/vendor/bundle/jruby/2.2.0/gems/google-api-client-0.9.6/generated/google/apis/bigquery_v2/service.rb:483)
        at RUBY.load(/hoge/access_log_loader/vendor/bundle/jruby/2.2.0/gems/embulk-output-bigquery-0.3.2/lib/embulk/output/bigquery/bigquery_client.rb:181)
        at RUBY.block in load_in_parallel(/hoge/access_log_loader/vendor/bundle/jruby/2.2.0/gems/embulk-output-bigquery-0.3.2/lib/embulk/output/bigquery/bigquery_client.rb:118)
​
Error: org.jruby.exceptions.RaiseException: (TransmissionError) execution expired
2016-06-07 16:02:11.856 +0900 [INFO] (0001:transaction): embulk-output-bigquery: delete /tmp/embulk_output_bigquery_20160607-9712-44afxy.9712.12832.jsonl.gz
2016-06-07 16:02:12.066 +0900 [INFO] (0001:transaction): embulk-output-bigquery: delete /tmp/embulk_output_bigquery_20160607-9712-44afxy.9712.12834.jsonl.gz
2016-06-07 16:02:12.092 +0900 [INFO] (main): Committed.

データ取得がタイムアウトする

原因と対策

データ量が増えるに従って処理が非常に遅くなってきました。

MySQLのデータベースからデータを取る所で30分タイムアウトに引っかかった様子です。
対象期間が大きすぎてデータ量が増えたかな?と思い、2016年5月30日の1日分を入れようとするだけでも、
タイムアウトエラーが出てしまいました。これではDailyBatchが動かせないので困ります。

selectを高速化させるために、FORCE INDEX (index_access_log_on_accessed_at) をつける事で解消しました。

サンプルエラーログ

org.embulk.exec.PartialExecutionException: java.lang.RuntimeException: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications
 link failure
​
The last packet successfully received from the server was 1,800,131 milliseconds ago.  The last packet sent successfully to the server was 1,8
00,125 milliseconds ago.
        at org.embulk.exec.BulkLoader$LoaderState.buildPartialExecuteException(org/embulk/exec/BulkLoader.java:363)
        at org.embulk.exec.BulkLoader.doRun(org/embulk/exec/BulkLoader.java:572)
        at org.embulk.exec.BulkLoader.access$000(org/embulk/exec/BulkLoader.java:33)
        at org.embulk.exec.BulkLoader$1.run(org/embulk/exec/BulkLoader.java:374)
        at org.embulk.exec.BulkLoader$1.run(org/embulk/exec/BulkLoader.java:370)
        at org.embulk.spi.Exec.doWith(org/embulk/spi/Exec.java:25)
        at org.embulk.exec.BulkLoader.run(org/embulk/exec/BulkLoader.java:370)
        at org.embulk.EmbulkEmbed.run(org/embulk/EmbulkEmbed.java:180)
        at java.lang.reflect.Method.invoke(java/lang/reflect/Method.java:606)
        at RUBY.run(uri:classloader:/embulk/runner.rb:84)
        at RUBY.run(uri:classloader:/embulk/command/embulk_run.rb:306)
        at RUBY.<top>(uri:classloader:/embulk/command/embulk_main.rb:2)
        at org.jruby.RubyKernel.require(org/jruby/RubyKernel.java:937)
        at opt.bin.embulk.embulk.command.embulk_bundle.<top>(file:/opt/bin/embulk!/embulk/command/embulk_bundle.rb:30)
        at java.lang.invoke.MethodHandle.invokeWithArguments(java/lang/invoke/MethodHandle.java:599)
        at org.embulk.cli.Main.main(org/embulk/cli/Main.java:23)
Caused by: java.lang.RuntimeException: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet successfully received from the server was 1,800,128 milliseconds ago.  The last packet sent successfully to the server was 1,800,121 milliseconds ago.

よくわからないがnil to integerで落ちるケースがある。

原因と対策

大量に転送していた中で2回程の以下のエラーに遭遇しました。
Embulkの不具合なのかはわかりませんが、対応策として以下2点が効きました。
・対象期間を短くする。
・リランする。

サンプルエラーログ

00:04:12.271 org.embulk.exec.PartialExecutionException: org.jruby.exceptions.RaiseException: (TypeError) no implicit conversion from nil to integer
00:04:12.271    at org.embulk.exec.BulkLoader$LoaderState.buildPartialExecuteException(org/embulk/exec/BulkLoader.java:363)
00:04:12.271    at org.embulk.exec.BulkLoader.doRun(org/embulk/exec/BulkLoader.java:572)
00:04:12.271    at org.embulk.exec.BulkLoader.access$000(org/embulk/exec/BulkLoader.java:33)
00:04:12.271    at org.embulk.exec.BulkLoader$1.run(org/embulk/exec/BulkLoader.java:374)
00:04:12.271    at org.embulk.exec.BulkLoader$1.run(org/embulk/exec/BulkLoader.java:370)
00:04:12.271    at org.embulk.spi.Exec.doWith(org/embulk/spi/Exec.java:25)
00:04:12.271    at org.embulk.exec.BulkLoader.run(org/embulk/exec/BulkLoader.java:370)
00:04:12.271    at org.embulk.EmbulkEmbed.run(org/embulk/EmbulkEmbed.java:180)
00:04:12.271    at java.lang.reflect.Method.invoke(java/lang/reflect/Method.java:606)
00:04:12.271    at RUBY.run(uri:classloader:/embulk/runner.rb:84)
00:04:12.271    at RUBY.run(uri:classloader:/embulk/command/embulk_run.rb:306)
00:04:12.271    at RUBY.<top>(uri:classloader:/embulk/command/embulk_main.rb:2)
00:04:12.271    at org.jruby.RubyKernel.require(org/jruby/RubyKernel.java:937)
00:04:12.271    at opt.bin.embulk.embulk.command.embulk_bundle.<top>(file:/opt/bin/embulk!/embulk/command/embulk_bundle.rb:30)
00:04:12.272    at java.lang.invoke.MethodHandle.invokeWithArguments(java/lang/invoke/MethodHandle.java:599)
00:04:12.272    at org.embulk.cli.Main.main(org/embulk/cli/Main.java:23)
00:04:12.272 Caused by: org.jruby.exceptions.RaiseException: (TypeError) no implicit conversion from nil to integer
00:04:12.272    at org.jruby.RubyArray.[]=(org/jruby/RubyArray.java:1382)
00:04:12.272    at RUBY.block in load_in_parallel(/hoge/mf_etl/vendor/bundle/jruby/2.2.0/gems/embulk-output-bigquery-0.3.2/lib/embulk/output/bigquery/bigquery_client.rb:124)
00:04:12.272    at RUBY.block in all_waits(uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/thwait.rb:40)
00:04:12.272    at RUBY.all_waits(uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/thwait.rb:127)
00:04:12.272    at RUBY.all_waits(uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/thwait.rb:39)
00:04:12.272    at RUBY.load_in_parallel(/hoge/mf_etl/vendor/bundle/jruby/2.2.0/gems/embulk-output-bigquery-0.3.2/lib/embulk/output/bigquery/bigquery_client.rb:122)
00:04:12.272    at RUBY.transaction(/hoge/mf_etl/vendor/bundle/jruby/2.2.0/gems/embulk-output-bigquery-0.3.2/lib/embulk/output/bigquery.rb:316)
00:04:12.272    at RUBY.transaction(uri:classloader:/embulk/output_plugin.rb:64)
00:04:12.272    at RUBY.block in transaction(uri:classloader:/embulk/filter_plugin.rb:54)
00:04:12.272    at RUBY.transaction(/hoge/mf_etl/vendor/bundle/jruby/2.2.0/gems/embulk-filter-eval-0.1.0/lib/embulk/filter/eval.rb:19)
00:04:12.272    at RUBY.transaction(uri:classloader:/embulk/filter_plugin.rb:51)
00:04:12.272    at RUBY.block in transaction(uri:classloader:/embulk/filter_plugin.rb:54)
00:04:12.272    at RUBY.transaction(/hoge/mf_etl/vendor/bundle/embulk/filter/add_mf_channel.rb:23)
00:04:12.272    at RUBY.transaction(uri:classloader:/embulk/filter_plugin.rb:51)
00:04:12.272    at RUBY.run(uri:classloader:/embulk/runner.rb:84)
00:04:12.272    at RUBY.run(uri:classloader:/embulk/command/embulk_run.rb:306)
00:04:12.272    at RUBY.<top>(uri:classloader:/embulk/command/embulk_main.rb:2)
00:04:12.272    at org.jruby.RubyKernel.require(org/jruby/RubyKernel.java:937)
00:04:12.272    at opt.bin.embulk.embulk.command.embulk_bundle.<top>(file:/opt/bin/embulk!/embulk/command/embulk_bundle.rb:30)
00:04:12.272 
00:04:12.272 Error: org.jruby.exceptions.RaiseException: (TypeError) no implicit conversion from nil to integer

 

まとめ

本稿ではEmbulkを活用して83億レコードのデータをどうやって移行していくかについてご紹介しました。
まとめると、
・対象期間は短めに期間を刻んでデータを入れると安定する
・TimeOut防止のオプション、Force indexを有効に利用する
事で、順調にデータが移行できました。
また、Embulkを利用する事でBigQueryのコストも低コストに抑える事が出来ました。

数十億レコードであれば、少しのコストでデータを移行する事が出来、
分析や調査にBigQueryの高速な検索を利用できるので是非みなさんも試してみてください。
 

おわりに

マネーフォワードでは、新しい取り組みにワクワクできるような仲間を募集しています。
ご応募お待ちしています。

【採用サイト】
マネーフォワード採用サイト
Wantedly | マネーフォワード

【プロダクト一覧】
家計簿アプリ・クラウド家計簿ソフト『マネーフォワード』
家計簿アプリ・クラウド家計簿ソフト『マネーフォワード』 iPhone,iPad
家計簿アプリ・クラウド家計簿ソフト『マネーフォワード』 Android
クラウド型会計ソフト『MFクラウド会計』
クラウド型請求書管理ソフト『MFクラウド請求書』
クラウド型給与計算ソフト『MFクラウド給与』
経費精算システム『MFクラウド経費』
消込ソフト・システム『MFクラウド消込』
マイナンバー対応『MFクラウドマイナンバー』
創業支援トータルサービス『MFクラウド創業支援サービス』
お金に関する正しい知識やお得な情報を発信するウェブメディア『マネトク!』

Pocket