書き込み
このページでは、Bigtable に送信できる書き込みリクエストのタイプの一覧を示します。また、それぞれの書き込みリクエストに関して、それを使用すべき場合と使用すべきでない場合について説明します。書き込み時にセル内のデータを集計する方法については、書き込み時に値を集計するをご覧ください。
Bigtable Data API とクライアント ライブラリを使用すると、プログラムによってテーブルにデータを書き込むことができます。Bigtable はそれぞれの書き込みに対してレスポンス(確認応答)を返します。
各クライアント ライブラリには、次のタイプの書き込みリクエストを送信する機能があります。
- 単純な書き込み
- インクリメントと追加
- 条件付き書き込み
- バッチ書き込み
Bigtable クライアント ライブラリには、単純な書き込みとバッチ書き込み用に、スマート再試行機能が組み込まれています。これにより、一時的に可用性が損なわれた状態をシームレスに処理します。たとえば、アプリケーションがデータの書き込みを試行して、一時的なサービス停止またはネットワークの問題が発生した場合は、書き込みが commit されるかリクエストの期限に達するまで自動的に再試行が行われます。この耐障害性は、単一クラスタ ルーティングまたはマルチクラスタ ルーティングを通じて、単一クラスタのインスタンスと複製されたインスタンスの両方で機能します。
バッチ書き込みオペレーションとストリーミング書き込みオペレーションの場合は、Bigtable Beam コネクタを使用できます。詳細については、バッチ書き込みをご覧ください。
書き込みリクエストに適用される上限については、割り当てと上限をご覧ください。
このページで説明する書き込みリクエストの Cloud Bigtable クライアント ライブラリの例については、書き込みの例をご覧ください。
書き込みのタイプとそれらを使用する場合
すべての書き込みリクエストには、次の基本コンポーネントが含まれます。
- 書き込み先のテーブルの名前。
- アプリ プロファイル ID。トラフィックのルーティング方法を Bigtable に伝えます。
- 1 つ以上のミューテーション。 ミューテーションは次の要素で構成されています。
- 列ファミリー名
- 列修飾子
- タイムスタンプ
- テーブルに書き込む値
ミューテーションのタイムスタンプのデフォルト値は現在の日時です。これは、Unix エポック(1970 年 1 月 1 日 00:00:00 UTC)からの経過時間として測定されます。
Bigtable に送信するタイムスタンプは、ミリ秒以下の精度を持つマイクロ秒の値にする必要があります。マイクロ秒精度のタイムスタンプ(3023483279876543
など)は拒否されます。この例では、指定できるタイムスタンプ値は 3023483279876000
です。
1 回の書き込みリクエストに含まれるミューテーションのタイムスタンプは、オーバーライドしない限りすべて同一です。書き込みリクエスト内のすべてのミューテーションのタイムスタンプを同一にすることもできれば、それぞれ異なるようにすることもできます。
単純な書き込み
MutateRow
リクエストを使用すると、Bigtable に単一行を書き込むことができます。リクエストでは、テーブル名、使用するアプリ プロファイルの ID、行キーが指定されていて、その行のミューテーションを 100,000 個まで含めることができます。 単一行の書き込みはアトミックです。単一行に対して複数のミューテーションを作成する場合は、この書き込みタイプを使用します。
単純な書き込みリクエストの送信方法を示すコードサンプルについては、単純な書き込みの実行をご覧ください。
単純な書き込みを使用すべきでない場合
以下のユースケースでは、単純な書き込みは最適なデータ書き込み方法ではありません。
連続した行キーが含まれるデータのバッチを書き込む場合。この場合は、単純な書き込みを連続して行う代わりに、バッチ書き込みを使用することをおすすめします。連続行のバッチを 1 回のバックエンド呼び出しで適用できるためです。
高スループット(1 秒あたりの行数または 1 秒あたりのバイト数)が必要であり、低レイテンシが必須ではない場合。この場合は、バッチ書き込みの方が高速です。
集計(増分を含む)
集計は、データの書き込み時にセル値を集計する Bigtable テーブルセルです。使用できる集計の種類は次のとおりです。
- 合計 - カウンタをインクリメントするか、実行中の合計を保持します。
- 最小値 - セルに整数を送信します。Bigtable は、現在のセル値と送信された値の低い方の値を保持します。セルがまだ存在しない場合は、送信された値を保持します。
- 最大値 - 値を含むセルに整数を送信すると、Bigtable は 2 つの値のうち大きい値を保持します。
- HyperLogLog(HLL) - セルに追加されたすべての値の確率セットに追加される値を送信します。
集計セルを更新するリクエストは、MutateRow
リクエストと、AddToCell
または MergeToCell
のいずれか、または削除ミューテーション タイプのいずれかのミューテーション タイプとともに送信されます。集計列ファミリーと集計タイプの詳細については、書き込み時に値を集計するをご覧ください。
最後に追加
既存の値にデータを追加するには、ReadModifyWriteRow
リクエストを使用します。このリクエストには、テーブル名、使用するアプリ プロファイルの ID、行キー、データ書き込み時に使用する一連のルールが含まれます。各ルールには、列ファミリー名と列修飾子、さらには追加値とインクリメント量のいずれか一方を含めます。
ルールは順番に適用されます。たとえば、リクエストの中に値 some
を含む列の値に文字列 thing
を追加するリクエストが含まれていて、同じリクエスト内の後にあるルールでその同じ列に body
を追加する場合、値は単一のアトミック書き込みで 2 回変更され、結果の値は somethingbody
になります。後のルールによって前のルールが上書きされてしまうことはありません。
ReadModifyWriteRow
呼び出しで整数をインクリメントすることもできますが、代わりに集計セルと AddToCell
または MergeToCell
を使用することをおすすめします。値を ReadModifyWrite
を使用してインクリメントできるのは、その値が 64 ビット ビッグ エンディアン符号付き整数としてエンコードされている場合に限られます。Bigtable は、空の値または存在しない値に対するインクリメントは、値がゼロである場合と同様に扱います。
ReadModifyWriteRow
リクエストはアトミックです。なんらかの理由で失敗しても、再試行されません。
ReadModifyWriteRow
を使用すべきでない場合
次のような場合は、ReadModifyWriteRow
リクエストを送信しないでください。
このユースケースは、
AddToCell
ミューテーションを含むMutateRow
リクエストを送信することで処理できます。詳細については、集計をご覧ください。複数クラスタ ルーティングが含まれるアプリ プロファイルを使用している場合。
複数の単一クラスタ アプリ プロファイルを使用していて、インスタンス内の他のクラスタの同じ行と列に書き込まれるデータと競合する可能性のある書き込みを送信する場合。単一クラスタ ルーティングでは、書き込みリクエストは単一クラスタに送信されてから複製されます。
クライアント ライブラリで提供されているスマート再試行機能に依存している場合。
ReadModifyWriteRow
リクエストを再試行することはできません。大量のデータを書き込み、書き込みを迅速に完了する必要がある場合。行を読み取ってからその行を変更するリクエストは、単純な書き込みリクエストよりも低速です。その結果、このタイプの書き込みは大規模な書き込みのための最適なアプローチではないことがよくあります。
たとえば、ページビューなど、数値が数百万規模のカウントを行う場合は、
AddToCell
ミューテーションでMutateRow
を行い、書き込み時にカウントを更新する必要があります。
条件付き書き込み
条件に照らして行を確認してから、その結果に応じて行にデータを書き込む場合は、CheckAndMutateRow
リクエストを送信します。 このタイプのリクエストには行キーと行フィルタが含まれます。行フィルタは、既存のデータの値を確認するために使用する一連のルールです。フィルタによって課される特定の条件が満たされている場合のみ、行の特定の列にミューテーションが commit されます。確認に続いて書き込みが行われるこのプロセスは、単一のアトミックな処理として完了します。
フィルタ リクエストには、次の 2 種類のミューテーションの一方または両方を含める必要があります。
- true ミューテーション(フィルタが値を返す場合に適用されるミューテーション)
- false ミューテーション(フィルタが何も返さない場合に適用されるミューテーション)
1 回の書き込みで、それぞれのタイプのミューテーション(true と false)を最大 100,000 個指定できます。少なくとも 1 つのミューテーションを送信する必要があります。すべてのミューテーションが完了すると Bigtable はレスポンスを送信します。
条件付き書き込みを送信する方法を示すコードサンプルについては、値の条件付き書き込みをご覧ください。
条件付き書き込みを使用すべきでない場合
以下のユースケースでは、条件付き書き込みを使用できません。
複数クラスタ ルーティングが含まれるアプリ プロファイルを使用している場合。
複数の単一クラスタ アプリ プロファイルを使用していて、インスタンス内の他のクラスタの同じ行と列に書き込まれるデータと競合する可能性のある書き込みを送信する場合。単一クラスタ ルーティングでは、書き込みリクエストは単一クラスタに送信されてから複製されます。
大量のデータを書き込み、書き込みを迅速に完了する必要がある場合。
ReadModifyWriteRow
と同様に、条件付き書き込みリクエストでは行を変更する前に行を読み取る必要があるため、CheckAndModifyRow
リクエストは単純な書き込みリクエストよりも遅くなります。その結果、このタイプの書き込みは大規模な書き込みのための最適なアプローチではないことがよくあります。
バッチ書き込み
MutateRows
リクエストを使用すると、1 回の呼び出しで複数の行を書き込むことができます。MutateRows
リクエストには、最大 100,000 個のエントリのセットが含まれ、各エントリがアトミックに適用されます。各エントリは、1 つの行キーと、その行に適用される 1 つ以上のミューテーションから構成されます。バッチ書き込みリクエストには、すべてのエントリを合わせて最大 100,000 個のミューテーションを含めることができます。たとえば、バッチ書き込みには次のような組み合わせを含めることができます。
- 各エントリに 1 個のミューテーションが含まれる 100,000 個のエントリ
- 100,000 個のミューテーションが含まれる 1 個のエントリ
- 各エントリに 100 個のミューテーションが含まれる 1,000 個のエントリ
MutateRows
リクエストの各エントリはアトミックですが、リクエスト全体はアトミックではありません。必要に応じて、Bigtable は、すべての書き込みが成功するか、リクエストの期限に達するまで、バッチ内の成功しなかったエントリを再試行します。次に、バッチの各書き込みと、書き込みの成否を示すレスポンスを返します。
バッチ書き込みの送信方法を示すコードサンプルについては、バッチ書き込みの実行をご覧ください。
バッチ書き込みを使用すべきでない場合
互いに近い位置にはない行にバルクデータを書き込む場合。Bigtable は、行キーの辞書的順番でデータを格納します。これは、バイナリのアルファベット順に相当します。このため、リクエスト内の行キーが互いに類似していない場合、Bigtable はそれらを並列処理せず、順次処理します。スループットは高くなりますが、レイテンシも長くなります。行キーが類似していて Bigtable が互いに近い位置にある行を書き込む場合にレイテンシが長くなるのを避けるには、
MutateRows
を使用します。行が互いに近い位置にない場合は、MutateRow
、つまり単純な書き込みを使用します。同じ行に対する複数のミューテーションをリクエストする場合。この場合は、1 回の単純な書き込みリクエストですべてのミューテーションを実行するほうがパフォーマンスが高くなります。なぜなら、単純な書き込みではすべての変更が 1 回のアトミックな処理で commit されるのに対して、バッチ書き込みでは同じ行に対してミューテーションを順次処理しなければならず、レイテンシが発生するためです。
バッチ書き込みのフロー制御
次のいずれかを使用してバッチ書き込み(削除を含む)を送信する場合は、コードでバッチ書き込みのフロー制御を有効にできます。
- Bigtable Beam コネクタ(
BigtableIO
) - Java 用 Bigtable クライアント ライブラリ
- Bigtable HBase Beam コネクタ(
CloudBigtableIO
) - Java 用 Bigtable HBase クライアント
Dataflow ジョブでバッチ書き込みのフロー制御を有効にすると、Bigtable は次の処理を自動的に実行します。
- トラフィックをレート制限して Bigtable クラスタの過負荷を回避する
- Bigtable の自動スケーリングをトリガーするためにクラスタの負荷が十分にあることを確認して(有効な場合)、必要に応じてさらにノードが自動的にクラスタに追加されるようにする
これらの組み合わせたアクションは、クラスタの過負荷とジョブの失敗を防ぐので、バッチ書き込みの実行を見越してクラスタの手動スケーリングを行う必要はありません。フロー制御が有効になっている場合、Dataflow ジョブの前ではなくこの実行中にクラスタ スケーリングが行われるため、クラスタを手動でスケーリングする場合よりもジョブの完了に時間がかかることがあります。
単一クラスタ ルーティング用に構成されたアプリ プロファイルを使用する必要があります。宛先クラスタの Bigtable 自動スケーリングを有効にする必要はありませんが、自動スケーリングでは、バッチ書き込みフロー制御を最大限に活用できます。Dataflow 自動スケーリングは、他のジョブと同様に使用できます。
Bigtable の自動スケーリングの詳細については、自動スケーリングをご覧ください。アプリ プロファイルのルーティング ポリシーについては、アプリ プロファイルの概要をご覧ください。
コードサンプルについては、バッチ書き込みのフロー制御を有効にするをご覧ください。
承認済みビューにデータを書き込む
承認済みビューにデータを書き込むには、次のいずれかを使用する必要があります。
- gcloud CLI
- Java 用 Bigtable クライアント
他の Bigtable クライアント ライブラリでは、承認済みビューのアクセス権限はまだサポートされていません。
承認済みビューにデータを書き込む場合は、テーブル ID に加えて承認済みビュー ID を指定します。
承認済みビューへの書き込みはすべて、基盤となるテーブルに直接適用されます。
承認済みビューの定義の制限事項
承認済みビューでは、データの書き込み先となる行または列は、承認済みビューの定義によって制限されます。つまり、書き込みできるのは、承認済みビューに指定された条件を満たす行と列のみです。
たとえば、承認済みビューが行キーの接頭辞 examplepetstore1
によって定義されている場合、examplepetstore2
の行キーを使用してデータを書き込むことはできません。行キー値の先頭には文字列 examplepetstore1
全体を含める必要があります。
同様に、承認済みビューが列修飾子の接頭辞 order-phone
によって定義されている場合、order-phone123
列修飾子を使用してデータを書き込むことができますが、order-tablet
列修飾子は使用できません。
書き込みリクエストでは、条件付き書き込みリクエストの値をチェックしようとする場合など、承認済みビュー外のデータを参照することもできません。
承認済みビューの外部のデータに書き込みまたは参照を行うリクエストの場合、PERMISSION_DENIED
のエラー メッセージが返されます。
レプリケーション
複製されたインスタンスの 1 つのクラスタが書き込みを受け取ると、その書き込みはインスタンス内の他のクラスタに直ちに複製されます。
アトミック性
マルチクラスタ インスタンスに送信する各 MutateRows
リクエストは、リクエストのルーティング先となるクラスタに対する単一のアトミック アクションとしてコミットされます。この書き込みがインスタンス内の他のクラスタに複製されると、それらの各クラスタも書き込みをアトミック オペレーションとして受け取ります。クラスタが部分的なミューテーションを受け取ることはありません。ミューテーションは、変更するすべてのセルに対してアトミックに適用され、全体が成功するか失敗するかのいずれかになります。
整合性
書き込んだデータが読み取りに使用できるようになるまでに要する時間は、インスタンス内のクラスタの数や、アプリ プロファイルで使用するルーティングのタイプなど、複数の要因によって左右されます。
単一クラスタ インスタンスでは、データはすぐに読み取り可能になりますが、インスタンスに複数のクラスタがある場合、つまりレプリケーションを使用している場合、Bigtable は結果整合性になります。リクエストを同一クラスタにルーティングすると、read-your-writes の整合性を実現できます。
書き込みリクエストを送信した後は、整合性トークンを作成して使用し、StandardReadRemoteWrites
モードで CheckConsistency
を呼び出すことができます。このトークンはレプリケーションの整合性を確認します。一般的には、書き込みのバッチが送信された後、または 1 時間などの特定の間隔の後に、整合性トークンを作成します。続いて、読み取りリクエストを行うモジュールなど、別のプロセスにトークンを渡してそのプロセスで使用することができます。そのプロセスでは、このトークンを使用して読み取り試行の前にすべてのデータが複製されていることを確認します。
トークンを作成した直後に使用する場合は、初回使用時の整合性の確認に数分かかることがあります。この遅延が発生するのは、各クラスタが他のすべてのクラスタをチェックして、追加のデータが送信されていないことを確認するためです。トークンの初回使用が完了している場合、またはトークンを初回使用する際に数分待機した場合、トークンの使用は即座に完了します。
競合の解決
Bigtable テーブルの各セルの値は 4 タプル(行キー、列ファミリー、列修飾子、タイムスタンプ)で一意に識別されます。これらの識別子の詳細については、Bigtable ストレージ モデルをご覧ください。まったく同じ 4 つのタプルの 2 つの書き込みが 2 つの異なるクラスタに送信された場合、Bigtable は、サーバー側の時間に基づいて最後の書き込みを優先する内部アルゴリズムを使用して、競合を自動的に解決します。Bigtable の「最後の書き込みの優先」の実装は確定的で、レプリケーションが完了すると、すべてのクラスタの 4 つのタプルが同じ値になります。