パーティション化されたデータ操作言語(パーティション化 DML)は、次のタイプの一括での更新と削除用に設計されています。
- 定期的なクリーンアップとガベージ コレクション。たとえば、古い行を削除したり、列を
NULL
に設定したりします。 - デフォルト値での新しい列のバックフィリング。たとえば、
UPDATE
ステートメントを使用して、現在NULL
になっている列の新しい値にFalse
を設定します。
パーティション化 DML は小規模なトランザクション処理には適していません。数行でステートメントを実行する場合は、識別可能な主キーでトランザクション DML を使用します。詳しくは、DML の使用をご覧ください。
多数の盲目的書き込みを commit する必要があるが、アトミック トランザクションは必要ない場合は、バッチ書き込みを使用して Spanner テーブルを一括変更できます。詳細については、バッチ書き込みを使用してデータを変更するをご覧ください。
Spanner データベースの統計情報テーブルから、アクティブなパーティション化 DML クエリとその進捗状況に関する分析情報を取得できます。詳細については、アクティブなパーティション化 DML の統計情報をご覧ください。
DML とパーティション化 DML
Spanner は、DML ステートメントの 2 つの実行モードをサポートしています。
DML はトランザクション処理に適しています。詳しくは、DML の使用をご覧ください。
パーティション化 DML は、キー空間を分割し、スコープの小さい個別のトランザクションでパーティションにステートメントを実行します。これにより、同時トランザクション処理に及ぼす影響を最小限に抑えながら、データベース全体にわたる大規模なオペレーションを実行できます。詳細については、パーティション化 DML の使用をご覧ください。
次の表に、2 つの実行モードの主な違いを示します。
DML | パーティション化された DML |
---|---|
WHERE 句と一致しない行がロックされる可能性があります。 |
WHERE 句と一致する行のみがロックされます。 |
トランザクション サイズに上限があります。 | Spanner がトランザクション数の上限とトランザクションごとの同時実行の制限を処理します。 |
ステートメントをべき等にする必要はありません。 | 整合性のある結果を保証するため、DML ステートメントをべき等にする必要があります。 |
トランザクションに複数の DML ステートメントと SQL 文を含めることができます。 | パーティション化されたトランザクションには、1 つの DML ステートメントのみを含めることができます。 |
ステートメントの複雑さに制限はありません。 | ステートメントは完全に分割可能でなければなりません。 |
クライアント コードに読み取り / 書き込みトランザクションを作成します。 | Spanner がトランザクションを作成します。 |
分割可能とべき等
パーティション化 DML ステートメントを実行する場合、1 つのパーティションの行から別のパーティションの行にアクセスすることはできません。また、Spanner によるパーティションの作成方法を制御することはできません。パーティショニングによりスケーラビリティが維持されますが、パーティション化 DML ステートメントは完全に分割可能でなければなりません。パーティション化 DML ステートメントは、一連のステートメントの結合として表現する必要があります。各ステートメントはテーブルの 1 つの行にのみアクセスし、他のテーブルにはアクセスできないように記述する必要があります。たとえば、複数のテーブルにアクセスしたり、自己結合を実行したりする DML ステートメントはパーティション化できません。DML ステートメントがパーティション化できない場合、Spanner は BadUsage
エラーを返します。
次の DML ステートメントは、各ステートメントがテーブルの単一行に適用できるため、完全なパーティション化が可能な状態です。
UPDATE Singers SET LastName = NULL WHERE LastName = '';
DELETE FROM Albums WHERE MarketingBudget > 10000;
次の DML ステートメントは、複数のテーブルにアクセスするため、完全なパーティション化はできません。
# Not fully partitionable
DELETE FROM Singers WHERE
SingerId NOT IN (SELECT SingerId FROM Concerts);
ネットワーク レベルの再試行が原因で、Spanner が一部のパーティションにパーティション化 DML ステートメントを複数回実行することがあります。結果として、1 つの行に対してステートメントが複数回実行される可能性があります。したがって、整合性のある結果を維持するため、ステートメントをべき等にする必要があります。1 つの行にステートメントを複数回実行しても同じ結果になる場合、ステートメントはべき等です。
次の DML ステートメントはべき等です。
UPDATE Singers SET MarketingBudget = 1000 WHERE true;
次の DML ステートメントはべき等ではありません。
UPDATE Singers SET MarketingBudget = 1.5 * MarketingBudget WHERE true;
行のロック
行が更新または削除の対象である場合にのみ、Spanner はロックを取得します。この動作は DML の実行と異なります。DML の場合、WHERE
句と一致しない行に読み取りロックを取得することがあります。
実行とトランザクション
DML ステートメントのパーティション化は、実行に選択したクライアント ライブラリのメソッドによって異なります。各クライアント ライブラリには、DML の実行用とパーティション化 DML の実行用のメソッドが用意されています。
クライアント ライブラリのメソッドの呼び出しでは、パーティション化 DML ステートメントを 1 つのみ実行できます。
Spanner は、テーブル全体に対してパーティション化 DML ステートメントをアトミックに適用しません。ただし、Spanner は各パーティションに対してパーティション化 DML ステートメントをアトミックに適用します。
パーティション化 DML は commit またはロールバックをサポートしていません。Spanner は、DML ステートメントを直ちに実行し、適用します。
- オペレーションをキャンセルした場合、Spanner は実行中のパーティションをキャンセルし、残りのパーティションを開始しません。Spanner は、すでに実行されているパーティションをロールバックしません。
- ステートメントの実行でエラーが発生すると、すべてのパーティションで実行が停止し、Spanner がオペレーション全体のエラーを返します。たとえば、データ型制約の違反、
UNIQUE INDEX
の違反、ON DELETE NO ACTION
の違反などのエラーを返します。実行が失敗した時点によっては、一部のパーティションでステートメントが正常に実行され、他のパーティションではパーティションが実行されていない可能性があります。
パーティション化 DML ステートメントが成功した場合、Spanner はキー範囲の各パーティションに対して少なくとも 1 回ステートメントを実行しています。
変更された行の数
パーティション化 DML ステートメントは、変更された行数の下限を返します。Spanner が変更された行をすべてカウントするとは限らないため、変更された行数が正確な値でない場合があります。
トランザクション数の制限
Spanner は、パーティション化 DML ステートメントの実行に必要なパーティションとトランザクションを作成します。トランザクション数の上限やトランザクションごとの同時実行の制限が適用されますが、Spanner はトランザクションがこの制限内に収まるように調整します。
Spanner では、データベースごとに最大 20,000 件のパーティション化 DML ステートメントを同時に実行できます。
サポートされていない機能
Spanner は、パーティション化 DML の一部の機能をサポートしていません。
INSERT
はサポートされていません。- Google Cloud コンソール: Google Cloud コンソールでパーティション化 DML ステートメントを実行することはできません。
- クエリプランとプロファイリング: Google Cloud CLI とクライアント ライブラリは、クエリプランとプロファイリングをサポートしていません。
- サブテーブル(別のテーブルまたは同じテーブルの別の行から読み取る)。
テーブル間の結合が必要なテーブルや変換などの複雑なシナリオでは、Dataflow コネクタの使用を検討してください。
例
次のコード例は、Albums
テーブルの MarketingBudget
列を更新します。
C++
ExecutePartitionedDml()
関数を使用して、パーティション化 DML ステートメントを実行します。
C#
ExecutePartitionedUpdateAsync()
メソッドを使用して、パーティション化 DML ステートメントを実行します。
Go
PartitionedUpdate()
メソッドを使用して、パーティション化 DML ステートメントを実行します。
Java
executePartitionedUpdate()
メソッドを使用して、パーティション化 DML ステートメントを実行します。
Node.js
runPartitionedUpdate()
メソッドを使用して、パーティション化 DML ステートメントを実行します。
PHP
executePartitionedUpdate()
メソッドを使用して、パーティション化 DML ステートメントを実行します。
Python
execute_partitioned_dml()
メソッドを使用して、パーティション化 DML ステートメントを実行します。
Ruby
execute_partitioned_update()
メソッドを使用して、パーティション化 DML ステートメントを実行します。
次のコード例では、SingerId
列に基づいて Singers
テーブルから行を削除します。
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
次のステップ
DML を使用してデータを変更する方法を確認する。
データ操作言語(DML)のベスト プラクティスについて学習する。
DML とミューテーションの違いについて、DML とミューテーションを比較するで確認する。
他のデータ変換シナリオについて、Dataflow コネクタの使用を検討する。