2022/08/31

BigQueryの料金について

BigQueryの基本的な料金

GCPの中でも BigQueryは特徴あって魅力的なサービスだと思いますが、実際に使ってみると「利用料金がいつの間にかとんでもない金額になっていた」ことで有名です。料金がかるのは、基本は以下の2つです。(実際にはストリーミングとかの別料金もありますが、あまり使われないはずなので割愛します)

価格は東京/大阪リージョン、$1=¥135換算です。


ストレージ:

$0.023=¥3.105/月/GB
$0.016=¥2.16/月/GB(長期保存:90日以上連続して変更されなかったテーブル/パーティション)
1TBまでは無料。

検索:

$6.00=¥810/TB (検索対象になったデータに対して課金)
1TBまでは無料。


BigQueryの検索が速い仕組み=料金が高騰する仕組み?

この章は私の主観や予想を含みます。

検索が速いのがBigQueryの最大の魅力と思いますが、実は裏では結構な大規模なインスタンスが動いているのではないかと思います。その根拠は「クエリジョブ」の以下の記載です。

オンデマンド料金では、プロジェクトで最大 2,000 個の同時実行スロットを設定できます。

ここで「スロット」が何なのか問題になりますが、「コミットメント」に以下の様に説明されています。

スロットは、BigQuery で使用される仮想 CPU を表しています。

つまりGCEのvCPUやGKEのノードと同等のもの? でしょうか。

GCEでvCPUを2000予約する費用を試算してみます。どのようなタイプのvCPUを選ぶかにもよりますが、n2-standard-80(vCPU=80、メモリ320GB、$4.9835/時間)だと、以下のとおり。

$4.9835*2000/80=$124.5875≒¥16,819/時間

ちょっと微妙だったような... GCEのvCPUと同じという予想はハズレかもしれません。


検索の料金を安くする仕組み

がっつりBigQueryを使いながらも検索の料金をそれなりに抑えられるかもしれない仕組みが用意されています。一覧にすると以下のとおり。ちょこっと使いたい方は蚊帳の外です。

名称概要料金
月定額契約購入した瞬間から、30日間の定額料金です。$2,400=¥324,000/月/100スロット
年定額契約購入した瞬間から、1年間の定額料金です。$2,040=¥275,400/月/100スロット
Flex Slots指定した短期間だけ、秒単位で定額にします。$4.80=¥648/時間/100スロット
BI Engineオンメモリ検索で高速化。$0.0499/GB/時間


定額料金

文字どおりの定額料金です。最初の1か月または1年は、途中で止められないので注意が必要です。また上記の料金は100スロットであることにも注意が必要です。通常のオンデマンド検索は2000スロットなので、スロットが少ないと「契約してみたけど検索遅い」ということになりそうです。オンデマンドでは2000スロット以上を使用する手段が用意されていませんが、定額契約では2000スロットを超えて予約できるそうです。東京リージョンでは最大1000スロットまでしか予約できないようです。

年定額契約をある程度のスロット以上購入すると、おまけとして下記のBI Engineの容量もついてきます。年定額契約するなら、これも使わない手はないです。


Flex Slots

瞬間だけ定額という、変則的な料金プランです。使用する都度開始/終了を指定するようなので、定期的に決まった検索を行うなどの用途に向いています。購入するスロット数が多すぎると、購入に失敗することがあります。購入に成功すると解除するまで、秒単位で使っていても使わなくても課金されます。

上手く使えば費用と速度の両面で効果があるはずです。他プランとの組み合わせも可能です。


BI Engine

料金体系というより機能なのですが、別の料金体系を持っています。

Business Intelligence(以下BIと略)ツールのデータソースとしてBigQueryのテーブルを使用する場合に、レスポンスの改善や利用料金の低減の目的で使用します。BIツールとBigQueryを接続すると、ちょっとBIツールを操作しただけで何度も検索が発生していて、いつも間にかとんでもない金額を使ってしまうという悲劇を防げます。なんかのBIツールと組み合わせなければならないわけではないので、常時使うことも可能です。

検索をオンメモリで行うので非常に速いそうです。その検索用のメモリの予約した容量に応じて料金が決まります。素のBigQueryよりいろいろと制限が厳しく、BI Engineで検索できない場合、通常のBigQueryで検索され、料金もそちらのものとなります。


2022/07/06

GAEのインスタンス起動時間

動機

GAEのスタンダード環境では、言語によってインスタンスの起動時間に差があるのは、Java8を含む第1世代VMを利用している人には、良く知られた事実です。既に起動しているインスタンスがあっても、リクエストが増えて新たにインスタンスが起動される場合にも、この起動時間がかかります。そのためインスタンス起動が遅いと、時々レスポンスが悪く感じることになります。

昨年公式に公開されたJava17がいつの間にかGAEでもプレビュー版として使えるようになっていましたので、バージョンアップで起動時間がどう変化したか確かめてみたくなりました。それにSpringの起動時間も気になります。で、言語とそのバージョン + Webフレームワークの違いで、実際のインスタンス起動時間を計ってみました。


最初に断っておきますが、私が使用する(可能性のある)組み合わせのみの測定です。


測定条件・方法

  • 基本的にアプリはGoogleのサンプルに入っていたHelloWorld、それに最低限のログを加えたもの。
  • ただしJava8/Goは手元にあった単純なアプリ。Slim3やObjectifyなどは入っていないので、結果には影響しないはず。
  • SpringBootはGoogleのサンプルに入っていたHelloWorldそのままなので、バージョンは2.6.6。
  • GoのフレームワークはGin。
  • インスタンスクラスはF1。
  • インスタンスが立ち上がっていないことをGCPコンソールで確認してから、ブラウザからリクエスト開始。
  • Cloud Loggingに記録されたログにより、リクエストの到着から、リクエストハンドラの先頭に入れたログが出るまでの時間を計算。
  • それぞれ5回測定し、平均値を算出。
  • 1回測定ごとにGCPコンソールから手動でインスタンスを停止。次の実行まで数分間放置。

測定結果

フレームワーク
なしあり
言語Java82.063-
Java111.0553.737
Java170.9393.551
Go 1.160.1760.205

単位はms。


所感

Java8

過去の経験から3秒くらいと思っていたのですが、なんか早いという結果になりました。意外でしたが、ちょっと嬉しい。

Java11

VMの起動が早いのでしょうか。フレームワークなしならVM起動してても、ほとんど待たされている感覚はありません。PHP/Pythonと同じくらいの起動時間だと思われます。


Java17

まだプレビュー版であることはご理解ください。しかしJava11より少し早くなっているのはいいですね。


SpringBoot

JavaVMに1秒+Springに3秒弱という結果でした。ブラウザを触っていても「あれ、遅いかな」と感じたころに応答が描画される感じです。これだけで十分「使えない」と判断できます。
起動時間の4秒というのは、GAEのJavaというと8しかなかった時代に、起動が遅いといわれていた状況よりも悪くなっています。Springはサーバレスという考えのなかった時代の、「起動しておいて口開けて待っている」ことが前提の時代の産物だけに、時代遅れの遺物になってしまった感があります。
サーバレスでやりたいなら、潔くSpringは捨てましょう。


Go

インタプリタもVMも存在しない、ネイティブ実行されるだけあって、爆速です。ブラウザを触っていても、インスタンス起動が起きていることを全く感じることがありません。


Gin

「フレームワークというよりライブラリ」と言われるだけあって、遅延は30ms程度と、ほとんど影響がありません。SpringBootと対照的な結果ですが、時代が違うのでサーバレスも考慮された結果なのかもしれません。


(2022/07/14追記)

現在、GAEのJava17はプレビューから一般提供に格上げされています。

2022/06/25

残念なレガシーバンドルサービス

GAE/JのJava17対応


(2024/02/26追記)
本記事の内容はすでに古くなっています。また最初の公開時に記載内容に間違いがあった可能性があります。


 久しぶりにApp Engineのドキュメントを見たら、まだプレビュー版ですが、Java17の対応が載っていて驚きました。Java17って去年秋にリリースされたばかりなので、GCPの対応はまだ先かなと想像していたのですが、予想よりずっと早いようです。Java17はJava11以来のLTSなので、注目に値します。


ランタイムの世代

GAEのランタイムには第1世代と第2世代の2種類があります。これらは実行されるランタイムのバージョンが異なるだけでなく、第1世代のみGoogleが実装した拡張機能があります。
これらの拡張機能のうち、よく使われるのは以下ではないでしょうか。
  • Memcache : オンメモリのキャッシュ
  • Search API : Googleのサーチエンジンと同じ全文検索
  • Mail API : メールの送受信
  • Users API : Googleアカウントによるユーザ認証

ランタイムを選択するうえで、これらの機能が必要かどうかも分かれ目になります。

個人的にはまだ第1世代ランタイムであるJava8を使用していて、第2世代ランタイムに移行への移行はまだです。その理由がこれらの機能を使用したいからです。


代替サービス/ライブラリ

以前は第2世代ランタイムでは、前記の第1世代ランタイムでしか提供されない機能の代わりに、他のサービス/ライブラリを使用するように、Googleは説明していました。これらの代替手段は現在でも有効で、本来はこれらの代替手段で対応するものと思います。主なものは以下のとおり。 

Memcache → Memorystore (無料枠なし)
Search API → Elasticsearch
Mail API → SendGrid/Mailgun/Mailgrid など
Users API → Identity Platform/Firebase Authentication/OpenID Connect など


Memcacheは、有料のMemorystoreが嫌なら、ちょっと極端ですが諦めてもいいでしょう。

Search APIは、代わりとして気軽に使えるものが事実上ありません。

Mail APIは、SendGridのみ無料枠が用意されています。SendGridは使いやすくて性能も十分と思います。

Users APIは優秀な代替手段が用意されており、無料枠もあるので、積極的に置き換えるべきと思います。


これらのGAEの機能と同じような状況にあったのがDatastoreですが、Datastoreはすでにサービス終了しています。代わって登場したFirestoreには「Datastore互換モード」があるので、Datastoreとほぼ同じように使えます。DatastoreはJavaライブラリが使いにくいですが、Firestoreはいくらかライブラリが使いやすくなっています。個人的にはFirestoreネイティブモードに乗り換えました。


レガシーバンドルサービスの提供

Java17対応と同時に、第2世代ランタイムに「レガシーバンドルサービス」が提供されるようになっていることに気付いて2度びっくりしました。

レガシーバンドルサービス」は第2世代ランタイムから、第1世代ランタイムのこれらの拡張機能を使用するためのライブラリのようです。これを使用することで、第2世代ランタイムも第1世代ランタイムと同様に使用することが出来るようになるようです。


しかし残念なことに、一番使いたいSearch APIは提供されないようです。

Elasticsearchがあるとはいえ、ちょっと興味本位で調査したい場合や、商用であってもサービス立ち上げ直後で利益が出せるのがいつになるか不安な状態では、安くない月額固定料金のサービスへの乗り換えは厳しいです。


Googleの本音を予想

GAEの第1世代ランタイムに用意されていた拡張機能は、Googleがランタイム(Javaの場合はJavaVM)を独自拡張して実装したのではないかと想像しています (だからランタイムの存在しないGoにはこれらの拡張機能が提供されない)。

App Engineスタンダード環境のランタイム」を読んでいるとGoogleは、第1世代ランタイムを停止して第2世代ランタイムに移行させたいのではないかと思えてきます (実際すぐに第1世代ランタイムが止まることはないことは、「レガシーランタイムの長期サポート」に説明されています)。古くなったランタイムのメンテナンスが行われなくなるのは当然なのでずっと第1世代ランタイムがサポートされることはないのですが、第2世代ランタイムへの移行を促したいのは、ランタイムの独自拡張のメンテナンスも止めたいからではないでしょうか。

なかなか移行が進まない原因を探ったら第1世代ランタイムの拡張機能が原因だったから、第2世代でも利用できるように「レガシーバンドルサービス」という形で対処したものと思われます。


Search APIの代替が用意されない理由はちょっと想像できません。Googleにとっては自社製の検索エンジンの応用らしいので、技術的には用意できなくはないはずです。政治的な理由しか考えられません。Elasticsearchに誘導したい理由は何なのでしょう。