BATCH

複数のデータ操作言語(DML)文をアトミック性や分離性を維持して適用します。

複数のDML文を組み合わせて、1つのパーティションがターゲットの場合はアトミック性と分離性を確保し、複数のパーティションがターゲットの場合はアトミック性のみを確保します。データを利用する前に、バッチを使用して1つのパーティション内のすべてのDMLを適用し、アトミック性と分離性を確保します。マルチ・パーティション・バッチでは、アトミック性はパーティションごとに確保されますが、ロギングによって、データを利用する前にすべてのDMLを確実に適用することができます(分離性)。

1つのパーティションをターゲットとするバッチを効果的に構成すると、クライアント-サーバー間のトラフィックを削減し、単一行のミューテーションでテーブルを効率よく更新することができます。バッチは複数のパーティションをターゲットとすることもできます。この場合、アトミック性と分離性が必要です。マルチ・パーティション・バッチでは、スループットが低下し、レイテンシーが増加する場合があります。実行できる方法が他にない場合のみ、asynchronous文などのマルチ・パーティション・バッチを使用してください。

重要: バッチを実装または実行する前に、「挿入と更新のバッチ処理」を参照してください。

必要に応じて、バッチによりクライアント指定タイムスタンプを適用できます。

構文

BEGIN [UNLOGGED | LOGGED] BATCH 
[USING TIMESTAMP [epoch_microseconds]]
   dml_statement [USING TIMESTAMP [epoch_microseconds]];
   [dml_statement; ...]
APPLY BATCH;
表 1. 凡例
構文規則 説明
大文字 リテラル・キーワード。
小文字 リテラル以外。
イタリック体 変数値。ユーザー定義値と置き換えます。
[] 任意。角かっこ( [] )で任意指定のコマンド引数を囲みます。角かっこは入力しないでください。
( ) グループ。丸かっこ(( ))は、選択肢を含むグループを示します。丸かっこは入力しないでください。
| または。縦棒( | )で代替要素を区切ります。要素のいずれかを入力してください。縦棒は入力しないでください。
... 繰り返し可能。省略記号(...)は、構文要素を必要な回数だけ繰り返すことができることを示します。
'Literal string' 単一引用符( ' )でCQL文内のリテラル文字を囲みます。大文字を維持するには、単一引用符を使用します。
{ key : value } マップ・コレクション。中かっこ( { } )でマップ・コレクションまたはキーと値のペアを囲みます。コロンでキーと値を区切ります。
<datatype1,datatype2> セット、リスト、マップ、またはタプル。山かっこ(< >)で、セット、リスト、マップまたはタプル内のデータ型を囲みます。データ型はコンマで区切ります。
cql_statement; CQL文の終了。セミコロン( ; )ですべてのCQL文を終了します。
[--] コマンドライン・オプションとコマンド引数は、2つのハイフン(--)で区切ります。この構文は、引数がコマンドライン・オプションと間違われる可能性がある場合に役立ちます。
' <schema> ...</schema> ' 検索CQLのみ:単一引用符( ' )でXMLスキーマ宣言全体を囲みます。
@xml_entity='xml_entity_type' 検索CQLのみ:スキーマ・ファイルおよびsolrConfigファイル内のXML要素を上書きするための実体とリテラル値を示します。

バッチには以下の種類のdml_statementsを含めることができます。

LOGGED | UNLOGGED

複数のパーティションが関与している場合、バッチはデフォルトでログに記録されます。ロギングを有効にしてバッチを実行すると、すべてのバッチ操作が成功するか、すべてのバッチ操作が失敗します(アトミック性)。まず、シリアライズされたバッチを、そのバッチをBLOBデータとして消費するバッチログ・システム・テーブルに書き込みます。正常に書き込まれると、各行は保持(ヒンテッド)され、バッチログ・データは削除されます。ロギングにはパフォーマンス・ペナルティーが伴います。バッチログが他の2つのノードに書き込まれるためです。バッチ・サイズに関する警告や障害について、しきい値のオプションを使用できます。

UNLOGGEDは、ペナルティーをログに記録させずにバッチを実行します。操作が多すぎる場合や関係しているパーティションが多すぎる場合、ログに記録されないバッチでは警告が生成されます。単一パーティション・バッチ操作はデフォルトでログに記録されず、ログに記録されないバッチ操作としてはこの操作のみ推奨されます。

ログに記録されるバッチではアトミック性が確保されますが(つまり、バッチ内のすべてのDML文が成功するか、またはすべて失敗することが保証される)、その他のトランザクション制御はバッチ・レベルで実行されません。たとえば、バッチ操作が1つのパーティションに書き込まれない限り、バッチの分離性は確保されません。マルチ・パーティション・バッチ操作では、クライアントは、サーバーで他の行がまだ更新中であっても、バッチによって最初に更新された行を読み取ることができます。単一パーティション・バッチ操作では、クライアントは、バッチが完了するまでどの行の部分的な更新も読み取ることはできません。

USING TIMESTAMPS
BATCHで実行されるトランザクションの書き込み時間を設定します。
制約事項: USING TIMESTAMPでは、IF NOT EXISTS句を含むDML文などのLWT(軽量トランザクション)はサポートされていません。

デフォルトでは、データベースではバッチによって変更されたすべてのデータに同じタイムスタンプが適用されます。バッチ内の文の順序は関係ありません。したがって、バッチ文は、特定の順序でタイムスタンプを適用する必要があるデータの書き込みではあまり役立ちません。特定の順序で実行するには、クライアント指定タイムスタンプを使用する必要があります。

ユーザー定義タイムスタンプ

USING TIMESTAMP [epoch_microseconds]の後にエポック時間をマイクロ秒単位で指定します。時間を指定しない場合、現在の時刻が挿入されます。

すべてのDMLに対して同じタイムスタンプを使用するには、バッチの1行目に挿入します。
BEGIN BATCH USING TIMESTAMP [epoch_microseconds]
   DML_statement1;
   DML_statement2;
   DML_statement3;
APPLY BATCH;
個々のトランザクションの場合は、DMLの末尾に挿入します。
BEGIN BATCH
   DML_statement1;
   DML_statement2 USING TIMESTAMP [epoch_microseconds];
   DML_statement3;
APPLY BATCH;

クライアント指定タイムスタンプをすべてのDMLに適用する

レコードの挿入時にユーザー定義の日付を使用してVera Adrianの食費を挿入します。

BEGIN BATCH USING TIMESTAMP 1481124356754405
INSERT INTO cycling.cyclist_expenses 
   (cyclist_name, expense_id, amount, description, paid) 
   VALUES ('Vera ADRIAN', 2, 13.44, 'Lunch', true);
INSERT INTO cycling.cyclist_expenses 
   (cyclist_name, expense_id, amount, description, paid) 
   VALUES ('Vera ADRIAN', 3, 25.00, 'Dinner', true);
APPLY BATCH;
注: 2つの文を同じパーティションに組み合わせると、1つのテーブル・ミューテーションが作成されます。
レコードを縦方向に表示します。
EXPAND ON
タイムスタンプがすべて同じであることを確認します。
SELECT cyclist_name, expense_id,
        amount, WRITETIME(amount),
        description, WRITETIME(description),
        paid,WRITETIME(paid)
   FROM cycling.cyclist_expenses
WHERE cyclist_name = 'Vera ADRIAN';
両方のレコードが同じタイムスタンプで入力されています。
@ Row 1
------------------------+------------------
 cyclist_name           | Vera ADRIAN
 expense_id             | 2
 amount                 | 13.44
 writetime(amount)      | 1481124356754405
 description            | Lunch
 writetime(description) | 1481124356754405
 paid                   | True
 writetime(paid)        | 1481124356754405

@ Row 2
------------------------+------------------
 cyclist_name           | Vera ADRIAN
 expense_id             | 3
 amount                 | 25
 writetime(amount)      | 1481124356754405
 description            | Dinner
 writetime(description) | 1481124356754405
 paid                   | False
 writetime(paid)        | 1481124356754405

(2 rows)

IF NOT EXISTSを使用した以下のバッチのように、バッチのDML文で比較して設定する(compare-and-set:CAS)ロジックが使用されていると、エラーが返されます。

BEGIN BATCH USING TIMESTAMP 1481124356754405
  INSERT INTO cycling.cyclist_expenses 
     (cyclist_name, expense_id, amount, description, paid) 
     VALUES ('Vera ADRIAN', 2, 13.44, 'Lunch', true);
  INSERT INTO cycling.cyclist_expenses 
     (cyclist_name, expense_id, amount, description, paid) 
     VALUES ('Vera ADRIAN', 3, 25.00, 'Dinner', false) IF NOT EXISTS;
APPLY BATCH;
InvalidRequest: Error from server: code=2200 [Invalid query] message="Cannot provide custom timestamp for conditional BATCH"

条件付き更新のバッチ処理

軽量トランザクションとして導入された条件付き更新をバッチ処理します。ただし、基になるPaxos実装がパーティションレベルの細分性でのみ動作するため、条件付き更新を含むバッチは1つのパーティション内でのみ動作します。バッチ内の1つの文が条件付き更新である場合は、条件付きロジックがtrueを返す必要があり、それ以外の場合はバッチ全体が失敗します。バッチに2つ以上の条件付き更新が含まれている場合は、すべての条件がtrueを返す必要があり、それ以外の場合はバッチ全体が失敗します。以下の例では、条件付き更新のバッチ処理を示します。

購入レコードに値を挿入する文でIF条件句を使用しています。
BEGIN BATCH
  INSERT INTO purchases (user, balance) VALUES ('user1', -8) IF NOT EXISTS;
  INSERT INTO purchases (user, expense_id, amount, description, paid)
    VALUES ('user1', 1, 8, 'burrito', false);
APPLY BATCH;
BEGIN BATCH
  UPDATE purchases SET balance = -208 WHERE user='user1' IF balance = -8;
  INSERT INTO purchases (user, expense_id, amount, description, paid)
    VALUES ('user1', 2, 200, 'hotel room', false);
APPLY BATCH;
条件付きバッチでは、カスタム・タイムスタンプを適用することはできません。条件付きバッチ内のUPDATE文とDELETE文は、IN条件を使用して行をフィルター処理できません。

この例の続きでは、バッチ内で静的カラムを条件付き更新と一緒に使用する方法を示します。

カウンター更新のバッチ処理

カウンターのバッチでは、COUNTERオプションを使用する必要があります。カウンター更新は、DataStax Enterpriseの他の書き込みとは異なり、べき等演算ではないためです。

BEGIN COUNTER BATCH
  UPDATE UserActionCounts SET total = total + 2 WHERE keyalias = 523;
  UPDATE AdminActionCounts SET total = total + 2 WHERE keyalias = 701;
APPLY BATCH;
カウンター以外のバッチにカウンター・カラムを含めることができないように、カウンター・バッチのDML文にカウンター以外のカラムを含めることはできません。カウンター・バッチ文では、カスタム・タイムスタンプを適用できません。