本ページでは、Alibaba Cloud EMR 上で Delta Lake を使用する際に生じる代表的な質問について説明します。
テーブルを作成できませんが、原因は何ですか?
Delta Lake では、テーブル作成時に LOCATION パラメーターを指定する必要があります。このパラメーターは、テーブルデータを格納するディレクトリを指定し、結果として作成されるテーブルは Apache Spark 上の外部テーブルとなります。
そのディレクトリが既に存在するかどうかによって、動作が異なります:
-
ディレクトリが存在しない場合:Delta Lake は、ご指定のスキーマに基づいて新しいテーブルを作成します。
-
ディレクトリが既に存在する場合:ご指定のスキーマは、当該ディレクトリ内の Delta ログファイルに記録されたスキーマと完全に一致する必要があります。不一致があると、テーブル作成が失敗します。
ディレクトリ内に既存の Delta ログファイルを確認し、CREATE TABLE ステートメントのスキーマをそれに合わせて調整してください。
Spark Streaming により Delta Lake に多数の小ファイルが生成されるのはなぜですか?
Spark Streaming はデータを一連のミニバッチとして書き込み、各ミニバッチで 1 つ以上のファイルを生成します。バッチサイズが小さい場合や継続的に実行されている場合、ファイル数が急速に増加します。
応答レイテンシの要件に応じて、以下のいずれかの戦略を選択してください:
| 戦略 | 適用タイミング | トレードオフ |
|---|---|---|
| ミニバッチサイズを増加 | 数分程度のレイテンシが許容可能 | ファイル数が減少するが、エンドツーエンドレイテンシが若干増加 |
| 定期的に OPTIMIZE を実行 | リアルタイム応答が必要 | コンパクションのオーバーヘッドが頻繁に発生;実行間隔中にファイルが蓄積 |
両方の戦略を併用することも可能です。まず、ファイルの蓄積速度を抑えるためにミニバッチサイズを大きく設定し、その後、残ったファイルを定期的に OPTIMIZE でコンパクションします。
OPTIMIZE の実行時間が非常に長いのはなぜですか?
長期間 OPTIMIZE を実行していない場合、Delta Lake 内に多数の小ファイルが蓄積します。OPTIMIZE はこれらのすべてのファイルを読み取り・再書き込みを行うため、ファイル数に比例して実行時間が長くなります。
OPTIMIZE を定期的に実行するタスクを設定してください。適切な実行頻度はワークロードに依存します:
-
クエリパフォーマンスの向上: OPTIMIZE をより頻繁に (毎日またはそれ以上の頻度で) 実行します。
-
コスト削減を重視する場合:実行頻度を下げます。
1 日 1 回の OPTIMIZE ジョブは、出発点として適しています。特に、コンピューティングコストが低いオフピーク時間帯に実行することを推奨します。その後、実際のクエリ性能およびコスト状況に応じて、実行頻度を調整してください。
OPTIMIZE が失敗するのはなぜですか?
Delta Lake は楽観的ロック機構を採用しています。複数の書き込みトランザクションが同時にコミットされると、そのうちの 1 つが失敗します。OPTIMIZE 自体も書き込みトランザクションであるため、同時実行中の他の書き込みと競合する可能性があります。
OPTIMIZE が最も失敗しやすいのは、ストリーミングジョブが継続的にデータを削除または更新する場合です。これは、変更データキャプチャ(CDC)ワークフローで一般的なパターンです。一方、ストリーミングジョブが削除や更新を行わず、単にデータを追加(append)するだけの場合、OPTIMIZE は失敗しません。
競合を軽減するには、テーブルを時間単位でパーティション化し、各パーティションへのデータ書き込みが完了した後に OPTIMIZE を実行します。これにより、OPTIMIZE がアクティブな書き込みウィンドウと競合することを回避できます。
OPTIMIZE 実行後に小ファイルが残るのはなぜですか?
OPTIMIZE は小ファイルを大きなファイルにコンパクションしますが、元の小ファイルは削除しません。Delta Lake はスナップショット隔離をサポートするためにこれらのファイルを保持しており、コンパクション開始前に開始されたクエリは、引き続き元のファイルを読み取ってテーブルの一貫したスナップショットにアクセスできます。
コンパクション済みのファイルを削除するには、OPTIMIZE の後に VACUUM を実行します。VACUUM は、置き換え済みかつ保存期間(デフォルトで 7 日)を経過したファイルを削除します。
VACUUM 実行後に小ファイルが残るのはなぜですか?
VACUUM は、以下の 2 つの条件を満たすファイルのみを削除します:① OPTIMIZE によりマージ済みであること、② 保存期間を経過していること。デフォルトの保存期間は 7 日です。
ファイルがまだ保存期間内である場合、あるいはまだマージされていない場合、VACUUM はそれらをそのまま残します。削除対象となるよう確実にするには、まず OPTIMIZE を実行し、その後、保存期間が経過してから VACUUM を実行してください。
最近マージされた小ファイルを削除するにはどうすればよいですか?
最近マージされたファイルは、まだ 7 日間の保存期間内にあるため、デフォルトでは VACUUM により削除されません。この保存期間は、履歴スナップショットへのアクセスを保護するためのものであり、早期にファイルを削除すると、タイムトラベル機能を利用するクエリが失敗する可能性があります。
保存期間のチェックを無効化すると、削除対象となったファイルをまだ読み込んでいるアクティブなクエリが失敗する可能性があります。この操作を実行する前に、当該テーブルの履歴スナップショットにアクセスするクエリやストリーミングジョブが存在しないことを確認してください。
安全であることが確実な場合は、以下のいずれかの方法をご利用ください:
-
保存期間チェックを無効化:Spark 構成プロパティ
spark.databricks.delta.retentionDurationCheck.enabledをfalseに設定し、Spark ジョブ起動時にこのパラメーターを渡します。その後、短い保存期間を指定して VACUUM を実行します。 -
グローバルな保存期間を短縮:ファイル
spark-defaults.confにおいて、spark.databricks.delta.properties.defaults.deletedFileRetentionDurationをinterval 1 hourに設定します。この設定は、クラスター上のすべての Delta テーブルにグローバルに適用されます。
VACUUM 実行後に Delta ログファイルが残るのはなぜですか?
VACUUM はデータファイルを管理するものであり、Delta ログファイルは対象外です。Delta Lake は Delta ログファイルのライフサイクルを自動的に管理します:
-
10 回のコミットごとに、Delta Lake はログファイルをマージします。
-
マージ後、Delta Lake は期限切れのログファイルを特定して削除します。
-
Delta ログファイルのデフォルト保存期間は 30 日です。
手動による介入は不要です。多数のログファイルが存在する場合、それはまだ 30 日間の保存期間内であるか、あるいは 10 回のコミットに達していないためです。
Delta Lake は OPTIMIZE や VACUUM の自動スケジューリングをサポートしていますか?
いいえ。Delta Lake はランタイムではなくライブラリであるため、組み込みのスケジューラーを備えていません。OPTIMIZE および VACUUM は、外部から明示的にトリガーする必要があります。
Apache Airflow や cron ジョブなど、ワークフローのオーケストレーションシステム内で定期タスクを設定し、Delta テーブルに対してこれらのコマンドを定期的に実行するように構成してください。