行レベルの同時実行

行レベルのコンカレンシーは、行レベルで変更を検出し、同時書き込みが同じデータ ファイル内の異なる行を更新または削除したときに発生する競合を自動的に解決することで、同時書き込み操作間の競合を軽減します。

行レベルのコンカレンシーの要件

次のすべての要件が満たされると、行レベルのコンカレンシーが自動的に有効になります。

  • Databricks Runtime 14.3 LTS 以降の使用。
  • ソース テーブルではパーティションは使用されません。
  • ソース テーブルで削除ベクトルが有効になっています。 Databricks の削除ベクトルを参照してください。

パーティション テーブルでは、行レベルのコンカレンシーは許可されません。 ただし、削除ベクトルが有効になっている場合でも、パーティション テーブルは OPTIMIZE 操作と書き込み操作の間の競合を回避できます。 「行レベルのコンカレンシーの制限事項」を参照してください。

14.3 LTS より前の Databricks ランタイム バージョンについては、「 行レベルのコンカレンシーレガシ動作」を参照してください。

同時実行性における行レベルの競合行列

行レベルのコンカレンシーを持つソース テーブルの場合、次の表は、各分離レベルで競合する可能性がある書き込み操作のペアを示しています。

Operation INSERT (1) UPDATE、DELETE、MERGE INTO OPTIMIZE
INSERT 競合できない
UPDATE、DELETE、MERGE INTO WriteSerializable で競合が発生する可能性はありません。 同じ行を変更するときに Serializable で競合する可能性があります。 同じ行を変更すると競合する可能性があります。
OPTIMIZE 競合できない ZORDER BY を使用すると競合する可能性があります。 それ以外の場合は競合する可能性はありません。 ZORDER BY を使用すると競合する可能性があります。 それ以外の場合は競合する可能性はありません。

(1) このテーブルのすべての INSERT 操作は、同じテーブルからデータを読み取るサブクエリを含まない追加操作を記述します。 INSERT 同じテーブルから読み取るサブクエリを含む操作は、 MERGEと同じコンカレンシーをサポートします。

  • ID 列を持つテーブルは、同時実行トランザクションをサポートしていません。 ID 列を参照してください。
  • REORG 操作には、データ ファイルの書き換え時の OPTIMIZE と同じ分離セマンティクスがあります。 REORG を使用してアップグレードを適用する際は、テーブルのプロトコルが変更され、すべての進行中の操作と競合します。

行レベルのコンカレンシーでの書き込みの競合

行レベルのコンカレンシーがないソース テーブルの場合、次の表は、各分離レベルで競合する書き込み操作のペアを示しています。

Operation INSERT (1) UPDATE、DELETE、MERGE INTO OPTIMIZE
INSERT 競合できない
UPDATE、DELETE、MERGE INTO WriteSerializable で競合が発生する可能性はありません。 Serializable で競合する可能性があります。 パーティション分割を使用した競合の回避を参照してください。 Serializable と WriteSerializable で競合する可能性がある。 パーティション分割を使用した競合の回避を参照してください。
OPTIMIZE 競合できない ZORDER BYを使用しない限り、削除ベクトルが有効になっているテーブルで競合することはできません。 それ以外の場合は競合が発生する可能性があります。 ZORDER BYを使用しない限り、削除ベクトルが有効になっているテーブルで競合することはできません。 それ以外の場合は競合が発生する可能性があります。

(1) このテーブルのすべての INSERT 操作は、同じテーブルからデータを読み取るサブクエリを含まない追加操作を記述します。 INSERT 同じテーブルから読み取るサブクエリを含む操作は、 MERGEと同じコンカレンシーをサポートします。

  • ID 列を持つテーブルは、同時実行トランザクションをサポートしていません。 ID 列を参照してください。
  • REORG 操作には、データ ファイルの書き換え時の OPTIMIZE と同じ分離セマンティクスがあります。 REORGを使用してアップグレードを適用すると、テーブル プロトコルが変更され、進行中のすべての操作と競合します。

行レベルのコンカレンシーの制限事項

行レベルのコンカレンシーには制限が適用されます。 次の操作では、競合の解決は、書き込みの競合に対する通常のコンカレンシーに従います。 「行レベルのコンカレンシーなしでの書き込みの競合」を参照してください。

制限事項 説明
複雑な条件句 複合データ型 (構造体、配列、マップ)、非決定論的式、サブクエリ、および相関サブクエリの条件
MERGE 述語の要件 Databricks Runtime 14.2 では、 MERGE コマンドはターゲット テーブルの明示的な述語を使用して、ソース テーブルに一致する行をフィルター処理する必要があります
パフォーマンスのトレードオフ 行レベルの競合検出では、合計実行時間が長くなる可能性があります。 同時実行トランザクションが多数ある場合、ライターは競合の解決よりも待機時間を優先します

削除ベクトルのすべての制限事項もあてはまります。 制限事項を参照してください。

パーティション分割を使用して競合を回避する

競合マトリックスで "競合する可能性があります" とマークされているすべてのケースで、2 つの操作が同じファイル セットに影響を与える場合にのみ競合が発生します。 2 つのファイル セットを不整合にするには、操作条件で使用されるのと同じ列でテーブルをパーティション分割します。

Example:

テーブルが日付でパーティション分割されていない場合、コマンドUPDATE table WHERE date > '2010-01-01' ...DELETE table WHERE date < '2010-01-01'競合します。これは、両方が同じファイルを変更しようとする可能性があるためです。 dateでテーブルをパーティション分割すると、競合が回避されます。

カーディナリティの高い列でテーブルをパーティション分割すると、サブディレクトリの数が多いため、パフォーマンスの問題が発生する可能性があります。

明示的なパーティション フィルターとの競合を回避する

この例外は、異なるパーティションを更新する場合でも、同じパーティションを読み取る可能性がある同時 DELETEUPDATE、または MERGE 操作中に発生することがよくあります。 操作条件で分離を明示的にします。

// Problem: Condition can scan the entire table
deltaTable.as("t").merge(
    source.as("s"),
    "s.user_id = t.user_id AND s.date = t.date AND s.country = t.country")
  .whenMatched().updateAll()
  .whenNotMatched().insertAll()
  .execute()

// Solution: Add explicit partition filters
deltaTable.as("t").merge(
    source.as("s"),
    "s.user_id = t.user_id AND s.date = t.date AND s.country = t.country AND t.date = '" + date + "' AND t.country = '" + country + "'")
  .whenMatched().updateAll()
  .whenNotMatched().insertAll()
  .execute()

競合の例外

トランザクションの競合が発生すると、次のいずれかの例外が発生します。

コンカレント・アペンドエクセプション (ConcurrentAppendException)

この例外は、同時実行操作によって、操作で読み取られたのと同じパーティション (またはパーティション分割されていないテーブル内の任意の場所) にファイルが追加された場合に発生します。 INSERTDELETEUPDATE、または MERGE の各操作によってファイルが追加される可能性があります。

既定の WriteSerializable 分離レベルでは、データを読み取らずにデータを追加する INSERT 操作によって追加されたファイルは、操作と競合しません。 分離レベルが [Serializable] である場合、追加操作は競合する可能性があります。

Important

INSERT 操作は、複数の同時実行中の DELETEUPDATE、または MERGE 操作が INSERT 操作によって追加された値を参照する可能性があると、WriteSerializable モードで競合する可能性があります。 これを回避するには、次のようにします。

  • 同時実行 DELETEUPDATE、または MERGE 操作が追加されたデータを読み取らないようにする
  • 追加されたデータを読み取ることができる最大 1 つの DELETEUPDATE、または MERGE 操作がある

ConcurrentDeleteReadException

この例外は、同時実行操作が操作で読み取ったファイルを削除するときに発生します。 一般的な原因は、ファイルを書き換える DELETEUPDATE、または MERGE 操作です。

ConcurrentDeleteDeleteException

あなたの操作によって削除されるファイルが、同時に他の操作によっても削除されると、この例外が発生します。 これは、同じファイルを書き換える 2 つの同時実行圧縮操作によって発生する可能性があります。

MetadataChangedException

この例外は、同時実行トランザクションによって Delta テーブルのメタデータが更新されると発生します。 一般的な原因は、テーブル スキーマを更新する ALTER TABLE 操作または書き込みです。

ConcurrentTransactionException

この例外は、同じチェックポイントの場所を使用するストリーミング クエリが複数回同時に開始され、同時に Delta テーブルへの書き込みを試みる場合に発生します。 同じチェックポイントの場所で 2 つのストリーミング クエリを同時に実行しないでください。

プロトコルチェンジドエクセプション (ProtocolChangedException)

この例外は、次の場合に発生する可能性があります。

  • Delta Lake テーブルが新しいプロトコル バージョンにアップグレードされます (Databricks ランタイムのアップグレードが必要になる場合があります)
  • 複数のライターが同時にテーブルを作成または置き換える
  • 複数の執筆者が空のパスに同時に書き込んでいます

Delta Lake の機能の互換性とプロトコルに関する記事を参照してください。

行レベルの同時実行性の従来の動作

Databricks Runtime 13.3 LTS では、行レベルのコンカレンシーでは従来の動作が使用されます。

  • 削除ベクトルが必要です。 Databricks の削除ベクトルを参照してください。
  • 液体クラスタリングを使用するテーブルでは、行レベルのコンカレンシーが自動的に有効になります。

その他のリソース