Tech記事

Spark SQLのInsert Overwrite時のパーティション削除の挙動

Spark SQLにおけるInsert Overwrite時に、既存のデータは削除されますが、削除されるパーティションが状況によって変化します。既存テーブルに新規パーティションをOverwriteで書き込もうとしてテーブル全体を削除してしまわないように、これらの挙動を理解しておく必要があります。

partitionOverwriteMode パーティション指定 上書き範囲
static なし テーブル
static 明示 指定パーティション
dynamic なし 対象パーティション

実行例を見ていきましょう。挙動確認に使用するサンプルテーブルを作成します。

create table if not exists ex1 (
  id int,
  dt string)
using parquet
partitioned by (dt)
location 'file:///home/warehouse/ex1/';

初期データを入れます。

insert overwrite table ex1
values
  (0, '2019-08-01'),
  (1, '2019-08-01'),
  (2, '2019-08-02'),
  (3, '2019-08-02');

/*
spark-sql> select * from ex1;
1       2019-08-01
0       2019-08-01
2       2019-08-02
3       2019-08-02
Time taken: 0.074 seconds, Fetched 4 row(s)
*/

ケース1: static&パーティション指定なし

  • 静的パーティション上書きモード(partitionOverwriteMode=static)
  • パーティション指定なし
set spark.sql.sources.partitionOverwriteMode=static; -- default is `static`
insert overwrite table ex1
values (4, '2019-08-02');

/*
spark-sql> select * from ex1;
4       2019-08-02
Time taken: 0.068 seconds, Fetched 1 row(s)
*/

この場合、既存のすべてのパーティションが削除されます。

以下の書き方でも同じ結果になります。

set spark.sql.sources.partitionOverwriteMode=static; -- default is `static`
insert overwrite table ex1
partition (dt)
values (4, '2019-08-02');

ケース2: static&パーティション明示指定

  • 静的パーティション上書きモード(partitionOverwriteMode=static)
  • 書き込みパーティションを明示的に指定
set spark.sql.sources.partitionOverwriteMode=static; -- default is `static`

insert overwrite table ex1
partition (dt='2019-08-02')
values (4);

/*
spark-sql> select * from ex1;
1       2019-08-01
0       2019-08-01
4       2019-08-02
Time taken: 0.069 seconds, Fetched 3 row(s)
*/

この場合、正常に指定したパーティションのみ上書きされます

ケース3: dynamic

  • 動的パーティション上書きモード(partitionOverwriteMode=dynamic)
set spark.sql.sources.partitionOverwriteMode=dynamic; -- default is `static`
insert overwrite table ex1
values (4, '2019-08-02');

/*
spark-sql> select * from ex1;
1       2019-08-01
0       2019-08-01
4       2019-08-02
Time taken: 0.053 seconds, Fetched 3 row(s)
*/

動的上書きモードの場合、明示的にパーティションを指定せずとも、書き込み対象となったパーティションだけが正常に上書きされます。

ただし、AWS EMRを使用している場合、EMRFSのS3に最適化されたParquetコミッタの使用条件を満たさなくなるため、S3へのステージングが発生し、書き込み速度が大幅に低下します。EMRFS S3向けに最適化されたParquetコミッタの要件の詳細についてはこちらを確認してください。

おまけ: 上書きじゃなくて追加する

新規パーティションなら、明示的に指定するよりもInsert Intoの追加モードで挿入してしまうのが楽です。ただ、このモードでは実行が何らかの理由で複数回発生すると、重複やデータのインバランスが発生するため、使い所に注意しましょう。

set spark.sql.sources.partitionOverwriteMode=static; -- default is `static`
insert into table ex1
values (4, '2019-08-02');

/*
spark-sql> select * from ex1;
0       2019-08-01
1       2019-08-01
4       2019-08-02
3       2019-08-02
2       2019-08-02
Time taken: 0.073 seconds, Fetched 5 row(s)
*/
ABOUT ME
Arata Furukawa
DMM.com LLCでAIエンジニアをしてます。 このブログでは、ITに関する記事や、セミナーの開催、執筆、登壇の告知などをまとめています。アイコンは自作。