行レベルの同時実行
行レベルの同時実行性は、行レベルでの変更を検出し、並列書き込みによって同じデータ ファイル内の異なる行が更新または削除されるときに発生する競合を自動的に解決することで、並列書き込み操作間の競合を軽減します。
行レベルの同時実行の要件
行レベルの同時実行性は、以下のすべての要件が満たされた場合に自動的に有効になります。
- Databricks Runtime 14.3 LTS 以降を使用します。
- ソーステーブルはパーティションを使用しません。
- ソーステーブルは削除ベクトルが有効になっています。「Databricks の削除ベクトル」を参照してください。
パーティション分割されたテーブルは行レベルの同時実行性をサポートしていません。ただし、削除ベクトルが有効になっている場合、パーティションを持つテーブルはOPTIMIZEと書き込み操作との競合を回避できます。行レベルの同時実行性の制限を参照してください。
14.3 LTS より前の Databricks Runtime バージョンについては、「行レベルのコンカレンシーのレガシー動作」を参照してください。
行レベルの同時実行による競合マトリックス
行レベルの同時実行性を持つソーステーブルについて、次の表は、各独立性レベルで並列書き込み操作の各ペアがどのように動作するかを示しています。
並列メタデータ変更は、テーブル内のすべての結果に対する例外です。ALTER TABLE コマンドやテーブルスキーマを更新する書き込みなどのメタデータの変更により、INSERT を含むすべての並列書き込み操作が失敗する可能性があります。メタデータの変更の競合を参照してください。
操作のペア | WriteSerializable (default) | シリアライズ可能 |
|---|---|---|
INSERT (1) + INSERT | 競合できません | 競合できません |
INSERT + UPDATE、DELETE、MERGE INTO | 競合できません | 同じ行を変更すると競合が発生する可能性があります。 |
INSERT + OPTIMIZE | 競合できません | 競合できません |
UPDATE、DELETE、MERGE INTO + UPDATE、DELETE、MERGE INTO | 同じ行を変更すると競合が発生する可能性があります | 同じ行を変更すると競合が発生する可能性があります |
UPDATE、DELETE、MERGE INTO + OPTIMIZE |
|
|
OPTIMIZE + OPTIMIZE |
|
|
(1) このテーブルにおけるすべてのINSERT操作は、同じテーブルからデータを読み取るサブクエリを含まない追加操作を記述します。同じテーブルから読み取るサブクエリを含む INSERT 操作は、MERGE と同じ同時実行性をサポートします。
- ペアが競合する可能性がある場合、影響を受けるデータを読み取る操作のみが失敗します。テーブルを読み取らずにデータを追加する
INSERTは失敗する操作ではないため、再試行ロジックは並列のUPDATE、DELETE、またはMERGEに適用されます。 - ID カラムを持つテーブルは、並列トランザクションをサポートしません。ID 列を参照してください。
REORGデータ ファイルを書き換える場合、操作にはOPTIMIZEと同じ分離セマンティクスが存在します。REORGを使用してアップグレードを適用すると、テーブル プロトコルが変更され、進行中のすべての操作と競合します。
行レベルの同時実行性のない書き込みの競合
行レベルの同時実行性がないソーステーブルについて、次の表は、各独立性レベルで各並列書き込み操作のペアがどのように動作するかを示しています。
並列メタデータ変更は、テーブル内のすべての結果に対する例外です。ALTER TABLE コマンドやテーブルスキーマを更新する書き込みなどのメタデータの変更により、INSERT を含むすべての並列書き込み操作が失敗する可能性があります。メタデータの変更の競合を参照してください。
操作のペア | WriteSerializable (default) | シリアライズ可能 |
|---|---|---|
INSERT (1) + INSERT | 競合できません | 競合できません |
INSERT + UPDATE、DELETE、MERGE INTO | 競合できません | 競合する可能性があります。 |
INSERT + OPTIMIZE | 競合できません | 競合できません |
UPDATE、DELETE、MERGE INTO + UPDATE、DELETE、MERGE INTO | 競合する可能性があります。パーティショニングを使用した競合の回避を参照してください。 | 競合する可能性があります。パーティショニングを使用した競合の回避を参照してください。 |
UPDATE、DELETE、MERGE INTO + OPTIMIZE |
|
|
OPTIMIZE + OPTIMIZE |
|
|
(1) このテーブルにおけるすべてのINSERT操作は、同じテーブルからデータを読み取るサブクエリを含まない追加操作を記述します。同じテーブルから読み取るサブクエリを含む INSERT 操作は、MERGE と同じ同時実行性をサポートします。
- ペアが競合する可能性がある場合、影響を受けるデータを読み取る操作のみが失敗します。テーブルを読み取らずにデータを追加する
INSERTは失敗する操作ではないため、再試行ロジックは並列のUPDATE、DELETE、またはMERGEに適用されます。 - ID カラムを持つテーブルは、並列トランザクションをサポートしません。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のオペレーションによって追加されたファイルは、いずれのオペレーションとも競合しません。分離レベルが直列化可能な場合、追記によって競合が発生する可能性があります。
複数の並列DELETE、UPDATE、またはMERGEのオペレーションがINSERTのオペレーションによって追加された値を参照する可能性がある場合、WriteSerializableモードでも競合が発生する可能性があります。DELETE、UPDATE、またはMERGEのオペレーションが失敗するのは、追加されたデータを読み取るためです。これを回避するには:
- 並列の
DELETE、UPDATE、またはMERGEオペレーションによって、追加されたデータが読み込まれないようにしてください。 - 追加されたデータを読み取ることができる
DELETE、UPDATE、またはMERGE操作が最大 1 つあります
ConcurrentDeleteReadException
この例外は、並列操作によって、操作で読み取ったファイルが削除されたときに発生します。 一般的な原因は、ファイルを書き換えるDELETE 、 UPDATE 、またはMERGE操作です。
ConcurrentDeleteDeleteException
この例外は、並列操作によって、ユーザーの操作によっても削除されるファイルが削除された場合に発生します。 これは、同じファイルを書き換える 2 つの並列圧縮操作によって発生する可能性があります。
MetadataChangedException
この例外は、並列トランザクションが Delta Lake テーブルのメタデータを更新したときに発生します。一般的な原因は、ALTER TABLE操作、またはテーブルスキーマを更新する書き込みです。
ConcurrentTransactionException
この例外は、同じチェックポイント場所を使用するストリーミングクエリが同時に複数回起動され、同時に Delta Lake テーブルへの書き込みを試みた場合に発生します。同じチェックポイント場所を使用して、2 つのストリーミングクエリを同時に実行しないでください。
ProtocolChangedException
この例外は次の場合に発生する可能性があります:
- Delta Lake テーブルは新しいプロトコルバージョンにアップグレードされます(Databricks Runtime のアップグレードが必要になる場合があります)。
- 複数のライターが同時にテーブルを作成または置換しています
- 複数のライターが同時に空のパスに書き込んでいます
Delta Lake 機能の互換性とプロトコルを参照してください。
行レベルのコンカレンシー レガシー動作
Databricks Runtime 13.3 LTS では、行レベルのコンカレンシーはレガシー動作を使用します。
- 削除ベクトルが必要です。「Databricks の削除ベクトル」を参照してください。
- リキッドクラスタリングが有効になっているテーブルでは、行レベルの同時実行性が自動的に有効になります。