Skip to content

Instantly share code, notes, and snippets.

@munisystem
Last active June 22, 2022 12:53
Show Gist options
  • Save munisystem/527b0ed0df1c36ff67cfb7db7658158b to your computer and use it in GitHub Desktop.
Save munisystem/527b0ed0df1c36ff67cfb7db7658158b to your computer and use it in GitHub Desktop.
BigQuery memo

間違っていることも多いので鵜呑みにしない。

用語

  • Project BigQueryのトップコンテナ、PostgreSQLで言うそれ本体みたいな意味合い
  • Dataset Tableの集合体、PostgreSQLで言うデータベース的な意味合い
  • Table そのまんま、PostgreSQLで言うテーブル的な意味合い
    • TableはTimestampみたいなsuffixをつけておくと、BQ側がまとめて見やすい形にしてくれる
  • Job Queryの実行やデータの追加はJobを通して行われる、トランザクションの実行単位

料金体系

  • ストレージ使用量
  • クエリ実行料
  • ストリーミングインサート使用量

ストリーミングインサートについては別途述べる

権限周り

AWSでいうIAM Roleみたいなのは サービスアカウント というらしい。

サービスアカウントに対してどのサービスのどの権限を与えるみたいな設定が出来る。

ちなみにGCP内通信みたいなのはインスタンスにサービスアカウントを紐付けるだけでなんやかんややってくれるんだけど、 AWS側からなにかデータ送りたいみたいなのはキーの発行をして、SDK内で指定する必要がある、別途述べる。

SDK周りの話

Javascriptに限っての話。 https://googlecloudplatform.github.io/google-cloud-node/#/docs/bigquery/0.9.0/bigquery

クレデンシャルの話

GCP外からSDKを使って何かしようとすると鍵が必要になる。

AWS SDKは

  • 環境変数
  • $HOME/.aws/credentials

からクレデンシャル情報を自動的に呼んでくれるんだけど、GCP SDKではそれができない。

const bigquery = require('google-cloud/bigquery');
const client = ({
  projectId: "Project ID",
  keyFilename: "./credential.json"
});

みたいな形でクレデンシャル情報を含んだキーのパスを指定するか、

const bigquery = require('google-cloud/bigquery');
const client = ({
  projectId: "Project ID",
  credentials: {
    client_email: "mail@address",
    private_key: "{private_key_json}",
  }
})

みたいな感じで指定しなきゃいけない。

なのでAWS Lambdaとかで使いたい場合は、Applicationをzipで固めるタイミングで一緒にkeyを含めてあげる必要がある。

詳しくはここ見て。 https://googlecloudplatform.github.io/google-cloud-node/#/docs/bigquery/0.9.0/guides/authentication

ちなみにProjectIdはURLに書いてある。そのままコピペして。

Tableとスキーマについて

Datasetもそうだけど、BQではDatasetやTableがなかったらImport時に作るみたいな機能はない。

そのため、DatasetがあるかTableがあるかみたいなバリデーションが必要になる。

ここを参考にどうぞ。 https://github.com/munisystem/sandbox/blob/master/node/bq/src/index.js

スキーマの定義に関しては自分で頑張る必要がある。

作るタイミングはテーブル作成時にoptionsとして渡す。

const options = {
  schema: "Name:string"
};
client.dataset("dataset_name").createTable(tableName, options).then(() => {});

スキーマの定義はくっそ面倒くさく、カラム名:型 をカンマ区切りでくっつけたstring文字列もしくはObjectが必要。

const options = {
  schema: "Name:string,Age:integer,Birthday:date"
}

Objectで送れるって言うけど

const options = {
  schema: {Name:'string', Age:'integer', 'Birthday': date}
}

みたいな書きかただと STRING is not defined みたいなエラーが出てうまくいかない。

ImportとInsert

Tableにデータを送る方法としてImportとInsertがある。 ImportはCSVやJsonを指定してそれを一回GCP側にアップロードしたのち、BigQueryがデータをTableに反映させる。 InsertはObjectを指定して、それをテーブルに反映させる。

実は両者の大きな違いとして、Insertはバッファに一時送られてTableに即時反映されないってのがある。(ストリーミングインサート) Tableに反映されていないけれど、SQLを発行したらそれには応答してくれるのでデータ解析には使用できる。 しかしBufferは欠損するらしく、秒間500行以上を推奨している。(Fluentdから10000件を送ったら9984件になったらしい。)

その為データを確実に送りたいならimportを使うほうがいい。 https://googlecloudplatform.github.io/google-cloud-node/#/docs/bigquery/0.9.0/bigquery/table?method=insert

@south37
Copy link

south37 commented Apr 14, 2017

個人的なコメントですが、この知見すごく価値があると思うので、Qiita とかに公開して多くの人の目に触れる様にした方が世の中に与える価値が大きそう! 💡
(gist は google 検索経由くらいでしか辿り着けるイメージが無いので。。。)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment