将MongoDB的数据导入到BigQuery的mongobq方法
mongobq是什么
这是一个用于将MongoDB特定集合的数据导入BigQuery表格的命令行工具。
使用方式的预期设定
-
- fluent-plugin-bigqueryなどでBigQueryにログやトランザクション系のデータが登録済みである
-
- ログ中には商品IDなどは入っているが、商品の値段などの詳細データはMongoDBで管理されている
- 両者を JOIN して分析するために、MongoDB 上のマスタデータを BigQuery に日次バッチなどでインポートしたい
安装方式
因为我将其作为npm包发布,所以需要Node 0.10或更高版本。
$ npm install -g mongobq
源代码已在 GitHub 上公开。如果有任何意见、功能添加请求等,请联系此处。
另外,使用 mongobq 需要先注册 Google Cloud Platform。另外,使用时如果超过了免费限额,可能会产生费用,请注意。
用法
选项列表
Usage: mongobq [options]
Options:
-h, --help output usage information
-V, --version output the version number
--host <hostname> specifies a hostname for the mongod. (Default: "localhost")
--port <port> specifies the TCP port for the mongod. (Default: 27017)
-u, --username <username> specifies a mongodb username to authenticate
-p, --password <password> specifies a mongodb password to authenticate
-d, --database <database> specifies the name of the database
-c, --collection <collection> specifies the collection to export
-f, --fields <field1[,field2]> specifies a field or fields to include in the export
-q, --query <JSON> provides a JSON document as a query that optionally limits the documents returned in the export
-K, --keyfile <keyfile> specifies the key file path
-B, --bucket <bucket> specifies the Google Cloud Storage bucket name
-O, --path <path> specifies the output path of the bucket (Default: "/")
-X, --suffix <suffix format> specifies the suffix format (Default: "YYYYMMDDHHmmss")
-P, --project <project> specifies the project ID of Google Cloud Platform
-D, --dataset <dataset> specifies the dataset ID of BigQuery
-T, --table <table> specifies the table ID of BigQuery
-S, --schema <schemafile> specifies the table schema of BigQuery table to import
--autoclean clean after run
--async no wait load job
--nocompress nocompress data when upload to Google Cloud Storage
--dryrun run as dryrun mode
如果涵盖了工作中所使用的模式,就会增加很多选项。但我会举例说明一些典型的使用模式。通常这四种模式就足够了。请注意,下面的例子隐含了以下条件。
-
- localhost 上の MongoDB に接続
- 対象コレクションが MongoDB 上のデータが1GB以下である
例1:一切交给我模式
-
- GCS上の一時ファイルはインポート完了後に削除
-
- BigQuery のスキーマは MongoDB のコレクションデータから自動判定
- BigQuery のテーブル名は MongoDB のコレクション名と同じで良い
$ mongobq --database [dbname] --collection [collection-name] \
--project [bigquery-project] --dataset [bigquery-dataset] \
--keyfile [your-gcp-json-keyfile.json] \
--bucket [bucket-name] --autoclean
例2: 想要指定模式文件的模式。
-
- GCS上の一時ファイルはインポート完了後に削除
-
- BigQuery のスキーマはスキーマファイルで指定する
フォーマットはbqコマンドと同じ)
スキーマで指定されないフィールドは無視されます
BigQuery のテーブル名は MongoDB のコレクション名と同じで良い
$ mongobq --database [dbname] --collection [collection-name] \
--project [bigquery-project] --dataset [bigquery-dataset] \
--keyfile [your-gcp-json-keyfile.json] \
--bucket [bucket-name] --schema [schema.json] --autoclean
例3:为了备份数据并输出到指定的GCS目录中,保留数据。
-
- バックアップも兼ねて、GCS上の一時ファイルは残す
下記では今日の日付でディレクトリを作っています
スキーマは自動判定
BigQuery のテーブル名は MongoDB のコレクション名と同じで良い
$ mongobq --database [dbname] --collection [collection-name] \
--project [bigquery-project] --dataset [bigquery-dataset] \
--keyfile [your-gcp-json-keyfile.json] \
--bucket [bucket-name] --path `date +%Y%m%d`
給對這個方向有興趣的人提供額外的資訊。
为什么不使用mongoexport?
由于mongoexport导出的是BSON格式,所以不能直接导入BigQuery。虽然可以将其导出为CSV格式,但是无法直接导入包含数组数据的数据,因此如果要进行逗号分隔等处理,会非常麻烦和慢,所以我选择放弃了。
$ mongoexport -d test -c users
{ "_id" : { "$oid" : "54752d762300e880f600007e" } ... }
Mongobq的优点
-
- dryrunモードがある。dryrunモード時はGCPへの操作が行われない。一時ファイル名の確認や、スキーマの自動判定の結果が見たい場合などにどうぞ。
-
- GCSのバケットとディレクトリはなければ自動作成してくれる
-
- GCSにアップロード時に圧縮してくれる
-
- MongoDB のデータから BigQuery のスキーマデータを自動判定してくれる。MongoDB のArray は BigQuery の REPATED フィールドとして判定してくれる。
-
- MongoDB — 整形 –> GCS の転送を Node の Stream で実装しているので、どんなにサイズが大きいコレクションに対してもメモリ/ディスクの少ないサーバでも実行可能
1億レコードのコレクションをインポートしてもメモリは150MB程度だし、ディスク仕様は原則ゼロ
mongobq 的不足之处。
-
- ZIP圧縮の部分がCPUバウンドな処理で、1コア100%ごっつり持っていかれること
-
- 埋め込みオブジェクトに対応していない(JSON.stringify された結果が STRING 型としてインポートされる)
- スキーマ自動判定だと、数字データは全部 FLOAT になる。頑張れば整数判定もできたのですが、JavaScript には整数型はないので、初期リリースでは素直にそのまま処理することにしました。
处理时间的大致估计
原则上,处理时间与记录数成正比,而不是与数据大小成正比。我认为这取决于环境,但仅供参考,我将列出实际测试的数据。以下是从 AWS 的 us-east-1 区域的 m3.xlarge 实例导入到 BigQuery 时所花费的时间。
-
- 件数多め、データサイズは小さめ
約1億レコード、JSON出力時13.3GB(非圧縮): 4時間47分
件数少なめ、データサイズは大きめ
約500万レコード、JSON出力時34.7GB(非圧縮): 1時間50分
件数少なめ、データサイズは小さめ(これが本来の想定している使用方法)
約30万レコード、JSON出力時3MB(圧縮): 2分23秒
容量限制
由于正在进行流处理,因此原则上执行服务器的资源没有限制。另外,如果使用–uncompress选项,可以导入高达1TB的数据,除非是非常庞大的数据,否则应该是没问题的。基本上这是用于导入主数据,所以对于不断增长的事务型数据,建议使用fluent-plugin-bigquery进行流式插入。
为什么不是1.0版本?
因为我们依赖于 gcloud-node 这个依赖库的最新版本(在GitHub上的 master 分支)。我想使用在 gcloud-node 中新增的 GCS 的可恢复上传功能,但目前已发布的版本还没有加入该功能,所以我们采取了这样的解决方法。计划在 gcloud-node 的下一个版本发布时将其纳入,并将其作为1.0版本发布。
Mongobq自身在工作中也使用过,所以不能说没有bug,但在一定规模的数据上使用是经过验证的。