Help us understand the problem. What is going on with this article?

Embulkを用いたダミーデータの生成

開発中のシステムの動作検証をするとき、少なからずシードデータやダミーのデータが必要となることが多いと思います。

私が携わった業務の中でも「パフォーマンス検証用に十数カラム数千万レコードのデータを用意しなければ」ということがあり、その際Embulkが非常に役立ったため生地に残したいと思います。

Embulkの便利なところ

まずEmbulkとは、よく「Fluentdのバッチ版」と説明されますがその通りで、大量データの転送、加工(ETL)処理を行うことができます。

今回Embulkを扱うことの利点として以下が挙げられます。

  • 様々なプラグインを利用できる
  • インプット先、アウトプット先が多様
  • 設定ファイルを書くだけで実行できる

多数あるプラグインを用いることで、ファイルやDB、クラウドサービスまで様々なデータソースを利用することが可能です。
また、「どこからデータを取ってきて、どこに送るのか」、「データをどう変換・加工するのか」をyamlファイルだけで定義できるのですぐに使い始めることができます。

ダミーデータ生成

今回はランダムデータを生成してくれるembulk-input-randomjというインプットプラグインを利用します。

また、出力はホストPC内のCSVファイルとします。

プラグインのインストール

※ Embulk自体の実行環境は整っている前提とします。

embulk-input-randomjプラグインをインストールします。

$ embulk gem install embulk-input-randomj

設定ファイルを作成

作成するダミーデータのフォーマットを設定するため、下記に示すconfig.ymlファイルを作成します(ファイル名はすきに変更して大丈夫です)。
今回は気軽に試せるように生成するレコード数は少なく設定しています。

config.yml
in:
  type: randomj
  rows: 100
  threads: 4
  primary_key: id
  schema:
  - {name: id, type: long}
  - {name: name, type: string}
  - {name: hash, type: string, length: 16}
  - {name: hobby, type: string, null_rate: 1000}
  - {name: price, type: long}
  - {name: day, type: long, min_value: 1, max_value: 31}
  - {name: average, type: double}
  - {name: rate, type: double, min_value: -100, max_value: 100}
  - {name: flag, type: boolean}
  - {name: time, type: timestamp, format: '%Y-%m-%d %H:%M:%S'}
  - {name: date, type: timestamp, format: '%Y-%m-%d', start_date: 20180101, end_date: 20201231}

out:
  type: file
  path_prefix: output_
  file_ext: csv
  formatter:
    type: csv
    header_line: true
    charset: UTF-8
    newline: CRLF
    column_options:
      time: {format: '%Y-%m-%d %H:%M:%S'}
      date: {format: '%Y-%m-%d'}

randomjプラグインの設定について

randojプラグインの設定パラメータは次の通りです。

パラメータ名 説明
rows 生成するレコード数(スレッド単位)
threads スレッド数
primary_key 主キーカラムの指定。指定したカラムは連番の値となる。
schema カラムの設定

生成される総レコード数はrows * threadsの値となります。上記設定ファイルだと100 * 4 = 400レコード分だけ生成されます。

実行

次のコマンドでEmbulkを実行します。

$ embulk run config.yml

(なお、embulk preview config.ymlでdry-runもできます。)

処理が終了すると、実行ディレクトリ下にoutput_*.csvというファイルが複数生成されているのが確認できます。
ファイル数は並列実行数すなわちスレッド数とCPUコア数によって異なります。

$ ls -l
total 168
-rw-r--r--  1 uro3  staff    934  2 16 15:01 config.yml
-rw-r--r--  1 uro3  staff  16569  2 16 15:02 output_000.00.csv
-rw-r--r--  1 uro3  staff      0  2 16 15:02 output_001.00.csv
-rw-r--r--  1 uro3  staff  16639  2 16 15:02 output_002.00.csv
-rw-r--r--  1 uro3  staff      0  2 16 15:02 output_003.00.csv
-rw-r--r--  1 uro3  staff  16679  2 16 15:02 output_004.00.csv
-rw-r--r--  1 uro3  staff      0  2 16 15:02 output_005.00.csv
-rw-r--r--  1 uro3  staff  16643  2 16 15:02 output_006.00.csv
-rw-r--r--  1 uro3  staff      0  2 16 15:02 output_007.00.csv

生成するレコード数が少なかったり、threadsパラメータの値を低くすると空のファイルが生成されることもあります(上記実行例でも空ファイルが生成されてしまってますね)。

ファイルの中身を確認してみます。

$ head -n 5 output_000.00.csv
1,dQYp5qfwcs4LEG8tpXXcL9nk8T5z8p0b,6jrmeMklNClY6z9D,uQDLLqDIzEGr04lZ1sk1HfSBTtPXrC4d,2627,1,9319.759903806967,-60.2255006491297,true,2020-05-03 06:09:20,2019-12-18
2,2zzN94AhX7dKEPj7iYNqpa1bFzis44RW,ymz2GQL7gGXLDHAq,6mlKrDC3I0vfDVGppW7W4YRj19WlPyHX,5883,13,4519.424678970713,16.01039975680497,true,2020-05-26 17:54:12,2018-08-21
3,6Lh4yZlDd6bNJMi6JWjcFafcufP5CsYw,H7egv5rdCgPgOxGo,GfOFodiZgcm115ja4EnhXMrdGGEwiB4r,1323,28,750.4551048594033,29.261926615295117,true,2020-03-30 20:29:09,2018-07-01
4,QcN0omRoNepFEmXycolrfmF5EetNTWR0,yjty1bTTb9ns0o9L,WF7lS4Ules7qjh7ECsx4zVpB28JwWmUg,8218,27,1103.5836005487843,30.128739554862438,false,2020-06-05 18:59:53,2020-01-13
5,rUQc8nXMLa2S6Q2ecXOUODx0B2SPOtLF,2VuDAxO4cu1i5F9u,DFQMU8DpiCnf6WTbRvPzu4qSY2C5SU5N,385,25,7301.194699442833,6.115086705050664,true,2020-03-05 03:01:28,2019-01-02

設定通りのデータができているようです。

生成された複数のファイルを一つのファイルにまとめたいときはcatコマンドを使いましょう。

$ cat output_*.csv >> result.csv

もう少しリッチなダミーデータ

基本的に文字列は完全にランダムな値なのでなんだか味気ないですよね。
そこで、他のfilterプラグインを活用して少しだけデータをリッチにしてみましょう。

今回は下記のプラグインを利用します。

embulk-filter-gsubは正規表現にマッチした文字列を任意の文字列に変換するプラグインです。
embulk-filter-typecastはカラムの型をキャストするプラグインです。embulk-filter-gsubで変換するにはstring型にする必要があるため、このプラグインを利用して型を変換します。

インストールコマンドは次の通りです。

$ embulk gem install embulk-filter-gsub embulk-filter-typecast

新しくconfig_2.ymlという名前で設定ファイルを作成します。

config_2.yml
in:
  type: randomj
  rows: 100
  threads: 4
  primary_key: id
  schema:
  - {name: id, type: long}
  - {name: filename, type: string, length: 8}
  - {name: device, type: boolean}
  - {name: weekday, type: long, min_value: 0, max_value: 6}

filters:
- type: typecast
  columns:
  - {name: "device", type: string}
  - {name: "weekday", type: string}
- type: gsub
  target_columns:
    filename:
    - {type: regexp_replace, pattern: (^.*$), to: $1.txt}
    device:
    - {type: regexp_replace, pattern: 'true', to: PC}
    - {type: regexp_replace, pattern: 'false', to: SP}
    weekday:
    - {type: regexp_replace, pattern: '0', to: }
    - {type: regexp_replace, pattern: '1', to: }
    - {type: regexp_replace, pattern: '2', to: }
    - {type: regexp_replace, pattern: '3', to: }
    - {type: regexp_replace, pattern: '4', to: }
    - {type: regexp_replace, pattern: '5', to: }
    - {type: regexp_replace, pattern: '6', to: }

out:
  type: file
  path_prefix: output_
  file_ext: csv
  formatter:
    type: csv
    header_line: false
    charset: UTF-8
    newline: CRLF

filenameカラムにはサフィックスとして拡張子をつけるようにしました。
また、deviceカラムにはPCかSPという文字列が、weekdayカラムには曜日を表す文字列がそれぞれ入ります。

それでは実行してみます。

$ embulk run config_2.yml

生成されたファイルの中身を確認してみます。

$ head -n 5 output_000.00.csv
1,udbQMu8j.txt,SP,木
2,PwdY5iJb.txt,SP,金
3,gtB79Y5W.txt,SP,金
4,DFSVa32v.txt,SP,月
5,jqSdcCGu.txt,PC,日

これである程度規則のあるデータも作成することができました。

まとめ

Embulkのembulk-input-randomjプラグインを使うことでダミーデータを簡単に生成することができます。

今回はcsvファイルとして作成しましたが、他にもDBやクラウドストレージにデータ挿入することもできたいへん便利です。
なお、生成するレコード数や出力先によってはある程度のマシンパワーが必要となるのでご注意ください。

参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした