行レベルの同時実行
行レベルの同時実行性は、行レベルでの変更を検出し、並列書き込みによって同じデータ ファイル内の異なる行が更新または削除されるときに発生する競合を自動的に解決することで、並列書き込み操作間の競合を軽減します。
行レベルの同時実行の要件
テーブルにパーティションが定義されている場合、または削除ベクトルが有効になっていない場合、テーブルは行レベルの同時実行をサポートしません。行レベルの同時実行には、Databricks Runtime 14.2 以上が必要です。
パーティションを持つテーブルは行レベルの同時実行をサポートしていませんが、削除ベクトルが有効になっている場合は、 OPTIMIZEと他のすべての書き込み操作との間の競合を回避できます。行レベルの同時実行の制限事項を参照してください。
14.2 より前の Databricks Runtime バージョンについては、 「行レベルの同時実行のプレビュー動作 (レガシ)」を参照してください。
MERGE INTO 行レベルの同時実行性をサポートするには、Databricks Runtime 14.2 の Photon が必要です。Databricks Runtime 14.3 LTS 以降では、Photon は必要ありません。
行レベルの同時実行による競合マトリックス
次の表は、行レベルの同時実行性が有効になっている各分離レベルで、どの書き込み操作のペアが競合する可能性があるかを示しています。
INSERT (1) | UPDATE、DELETE、 MERGE INTO | OPTIMIZE | |
|---|---|---|---|
INSERT | 競合できません | ||
UPDATE、DELETE、 MERGE INTO | WriteSerializable では競合できません。同じ行を変更すると、Serializable で競合が発生する可能性があります。 | 同じ行を変更すると競合が発生する可能性があります。 | |
OPTIMIZE | 競合できません |
|
|
(1) この表のすべてのINSERT操作は、コミット前に同じテーブルからデータを読み取らない追加操作を表します。同じテーブルを読み取るサブクエリを含むINSERT操作は、 MERGEと同じ同時実行性をサポートします。
- ID カラムを持つテーブルは、並列トランザクションをサポートしません。 Delta Lake での ID 列の使用を参照してください。
REORGデータ ファイルを書き換える場合、操作にはOPTIMIZEと同じ分離セマンティクスが存在します。REORGを使用してアップグレードを適用すると、テーブル プロトコルが変更され、進行中のすべての操作と競合します。
行レベルの同時実行性のない書き込み競合
テーブルにパーティションが定義されている場合、または削除ベクトルが有効になっていない場合、テーブルは行レベルの同時実行をサポートしません。行レベルの同時実行には、Databricks Runtime 14.2 以上が必要です。
行レベルの同時実行性のない競合マトリックス
次の表は、各分離レベルで競合する可能性がある書き込み操作のペアを示しています。
INSERT (1) | UPDATE、DELETE、 MERGE INTO | OPTIMIZE | |
|---|---|---|---|
INSERT | 競合できません | ||
UPDATE、DELETE、 MERGE INTO | WriteSerializable では競合できません。Serializable で競合が発生する可能性があります。「パーティション分割を使用して競合を回避する」を参照してください。 | Serializable と WriteSerializable で競合が発生する可能性があります。「パーティション分割を使用して競合を回避する」を参照してください。 | |
OPTIMIZE | 競合できません |
|
|
(1) この表のすべてのINSERT操作は、コミット前に同じテーブルからデータを読み取らない追加操作を表します。同じテーブルを読み取るサブクエリを含むINSERT操作は、 MERGEと同じ同時実行性をサポートします。
- ID カラムを持つテーブルは、並列トランザクションをサポートしません。 Delta Lake での ID 列の使用を参照してください。
REORGデータ ファイルを書き換える場合、操作にはOPTIMIZEと同じ分離セマンティクスが存在します。REORGを使用してアップグレードを適用すると、テーブル プロトコルが変更され、進行中のすべての操作と競合します。
行レベルの同時実行の制限
行レベルの同時実行には制限が適用されます。次の操作では、書き込み競合の通常の同時実行に従って競合が解決されます。行レベルの同時実行性がない場合の書き込み競合を参照してください。
制限 | 説明 |
|---|---|
複雑な条件節 | 複雑なデータ型(構造体、配列、マップ)、非決定論的式、サブクエリ、相関サブクエリの条件 |
| Databricks Runtime 14.2 では、 |
パフォーマンスのトレードオフ | 行レベルの競合検出により、合計実行時間が長くなる可能性があります。並列トランザクションが多い場合、ライターは競合解決よりもレイテンシを優先します。 |
削除に関するすべての制限も適用されます。 制限事項を参照してください。
パーティション分割による競合の回避
競合マトリックスで「競合する可能性がある」とマークされているすべてのケースでは、2 つの操作が同じファイル セットに影響する場合にのみ競合が発生します。2 セットのファイルを分離するには、操作条件で使用される同じ列でテーブルをパーティション分割します。
例:
テーブルが日付でパーティション分割されていない場合、コマンドUPDATE table WHERE date > '2010-01-01' ...とDELETE table WHERE date < '2010-01-01'は両方とも同じファイルを変更しようとするため、競合します。テーブルをdateでパーティション分割すると競合を回避できます。
カーディナリティの高い列でテーブルをパーティション分割すると、サブディレクトリの数が多くなり、パフォーマンスの問題が発生する可能性があります。
例: 明示的なパーティションフィルタによる競合の回避
この例外は、異なるパーティションを更新する場合でも同じパーティションを読み取る可能性がある並列DELETE 、 UPDATE 、または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
この例外は、並列操作によって、操作が読み取るのと同じパーティション (またはパーティション化されていないテーブル内の任意の場所) にファイルが追加されたときに発生します。 ファイルの追加は、 INSERT 、 DELETE 、 UPDATE 、またはMERGE操作によって発生する可能性があります。
デフォルトの WriteSerializable 分離レベルでは、ブラインドINSERT操作 (データを読み取らずにデータを追加する操作) によって追加されたファイルは、どの操作とも競合しません。分離レベルが Serializable の場合、ブラインド追加で競合が発生する可能性があります。
複数の並列DELETE 、 UPDATE 、またはMERGE操作がブラインド追加によって挿入された値を参照する可能性がある場合、ブラインド追加はWriteSerializableモードで競合する可能性があります。 これを避けるには:
- 並列
DELETE、UPDATE、またはMERGE操作で追加されたデータが読み取られないようにしてください - 追加されたデータを読み取ることができる
DELETE、UPDATE、またはMERGE操作が最大 1 つあります
ConcurrentDeleteReadException
この例外は、並列操作によって、操作で読み取ったファイルが削除されたときに発生します。 一般的な原因は、ファイルを書き換えるDELETE 、 UPDATE 、またはMERGE操作です。
ConcurrentDeleteDeleteException
この例外は、並列操作によって、ユーザーの操作によっても削除されるファイルが削除された場合に発生します。 これは、同じファイルを書き換える 2 つの並列圧縮操作によって発生する可能性があります。
MetadataChangedException
この例外は、並列トランザクションがDeltaテーブルのメタデータを更新したときに発生します。 一般的な原因は、テーブル スキーマを更新するALTER TABLE操作または書き込みです。
ConcurrentTransactionException
この例外は、同じチェックポイントの場所を使用するストリーミング クエリが同時に複数回開始され、同時に Delta テーブルに書き込もうとした場合に発生します。同じチェックポイントの場所を持つ 2 つのストリーミング クエリを同時に実行しないでください。
ProtocolChangedException
この例外は次の場合に発生する可能性があります:
- Delta テーブルが新しいプロトコル バージョンにアップグレードされました (Databricks Runtime のアップグレードが必要になる場合があります)
- 複数のライターが同時にテーブルを作成または置換しています
- 複数のライターが同時に空のパスに書き込んでいます
Delta Lake 機能の互換性とプロトコルを参照してください。
行レベルの同時実行プレビュー動作(レガシー)
このセクションでは、Databricks Runtime 14.1 以前における行レベルの同時実行のプレビュー動作について説明します。
Databricks Runtimeのバージョン | 挙動 |
|---|---|
Databricks Runtime 13.3 LTS 以上 | リキッドクラスタリングを備えたテーブルでは、行レベルの同時実行が自動的に有効になります。 |
Databricks Runtime 14.0 および 14.1 | 以下の設定を使用して、削除ベクトルを持つテーブルの行レベルの同時実行を有効にします。 |
Databricks Runtime 14.1 以下 | Non-Photon コンピュートは、 |
Databricks Runtime 14.0 および 14.1 で行レベルの同時実行を有効にするには:
spark.databricks.delta.rowLevelConcurrencyPreview = true
行レベルの同時実行には常に削除ベクトルが必要です。