Databricksの継続的なロードパターン「COPY INTO」/「Auto Loder」の比較について【Unity Catalog環境下で検証】

## はじめに

Databricksの **COPY INTO** と **Auto Loader** の比較について記載します。

## COPY INTO と Auto Loaderどちらを利用すべきか

どちらもバッチ処理として利用可能ですが、ストリーム処理として継続可能なのは **Auto Loader** となります。

docsからは以下のような記載となっています。

>- 数千の順序でファイルを取り込む場合は、COPY INTO を使用できます。 時間の経過とともに数百万以上の順序のファイルが予想される場合は、自動ローダーを使用します。 自動ローダーでは、COPY INTO と比較してファイルを検出する操作の合計が少なくて済み、処理を複数のバッチに分割できます。つまり、自動ローダーの方がコストが低く、大規模で効率が高くなります。
>- データ スキーマが頻繁に展開する予定の場合は、自動ローダーにより、スキーマの推論と展開に関してより適切なプリミティブが得られます。 詳細については、「自動ローダーでのスキーマの推論と展開の構成」を参照してください。
>- 再アップロードされたファイルのサブセットの読み込みは、COPY INTO のほうが少し簡単に管理できます。 自動ローダーでは、選択したファイルのサブセットの再処理が難しくなります。 ただし、自動ローダー ストリームを同時に実行しながら、COPY INTO を使用して、ファイルのサブセットを再度読み込むことは可能です。

https://learn.microsoft.com/ja-jp/azure/databricks/ingestion/

サブセットの読み込みについては、COPY INTOではファイルの読み込み時にファイルパスに加えて正規表現による対象の絞り込みが効くことを示しているようです。

デイリーな処理では **COPY INTO** でシンプルに実装する。  
ニアリアルタイムな処理であったりマイクロバッチ的にファイル連携が行われる場合には　**Auto Loader** を利用するという分岐になりそうです。

## COPY INTO 

[COPY INTO](https://learn.microsoft.com/ja-jp/azure/databricks/spark/latest/spark-sql/language-manual/delta-copy-into)

### サンプル

[COPY INTO を使用した一般的なデータ ロード パターン](https://learn.microsoft.com/ja-jp/azure/databricks/ingestion/copy-into/examples)

```sql:sql

CREATE TABLE IF NOT EXISTS my_pipe_data;

COPY INTO my_pipe_data
  FROM 'abfss://container@storageAccount.dfs.core.windows.net/base/path'
  FILEFORMAT = CSV
  FORMAT_OPTIONS ('mergeSchema' = 'true',
                  'delimiter' = '|',
                  'header' = 'true')
  COPY_OPTIONS ('mergeSchema' = 'true');

```

### 検証

#### 初回ロード

マージスキーマを有効にして、ファイルのスキーマ変更に対応しつつロードしてみます。

1.テーブルを作成する

![2022-09-22-09-05-32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/2f504e4b-1f94-01f0-60e6-ea728801c9bd.png)


2.ファイルをアップする

![2022-09-22-09-06-55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/fc76f7e2-2199-6962-f820-6d5d3df5ce04.png)


3.COPY INTO を実行する

![2022-09-22-09-15-49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/a14ac3af-a279-3f1a-1bc2-29123222c5f4.png)


#### 取り込み済みの場合での再実行の確認と追加

再実行しても取り込み済みデータは無視されることを確認し、ファイルを追加して実行します。

追加ファイルは2行のcsv

```csv:csv

Order Number,Line Number,Product Code,Quantity,Order Date
231000505,0,0602011,99,2016-04-28
231201204,0,0602011,99,2016-04-30

```

1.再実行で無視を確認

![2022-09-22-09-16-10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/5ebe7ade-1371-7afd-f8de-b6f05a2fd879.png)

2.ファイル追加

![2022-09-22-09-16-30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/4e94624e-0ac0-4b48-280e-6253aef808f6.png)

3.再実行で取り込みを確認

![2022-09-22-09-16-49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/4627555f-ddd8-b412-0f4b-bfc767d745a9.png)


#### Unity Catalog上の履歴

※他の作業で発生した余計な実行は黒塗りしてます

![2022-09-22-09-59-55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/558f2819-e2ec-af68-d7b3-c9dafa5757da.png)

## Auto Loader


[Auto Loader](https://learn.microsoft.com/ja-jp/azure/databricks/ingestion/auto-loader/options)

Unity Catalog環境下になるのでシングルユーザーモードのクラスターで実行します※ジョブ実行時もシングルユーザーモードでの構成が必要ですが、既定のジョブクラスターはシングルユーザーモードなのでおそらく問題ないですね

### サンプル

[Unity Catalog で自動ローダーを使用する](https://learn.microsoft.com/ja-jp/azure/databricks/ingestion/auto-loader/unity-catalog)

```python:python

checkpoint_path = "s3://dev-bucket/_checkpoint/dev_table"

(spark.readStream
  .format("cloudFiles")
  .option("cloudFiles.format", "json")
  .option("cloudFiles.schemaLocation", checkpoint_path)
  .load("s3://autoloader-source/json-data")
  .writeStream
  .option("checkpointLocation", checkpoint_path)
  .trigger(availableNow=True)
  .toTable("dev_catalog.dev_database.dev_table"))

```

### 検証

#### 初回ロード

1.テーブルを作成する

![2022-09-22-09-53-37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/f345f3b7-910d-56a7-a204-95daf0a2caf3.png)


2.ファイルアップ（COPYINTOで使用したフォルダを流用）

![2022-09-22-09-53-27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/ef6d4f98-9d6d-3753-341d-55a1c08ddbb1.png)

3.AutoLoaderの実行

![2022-09-22-09-50-33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/d126001c-ab48-1356-47c0-97c44f17f52c.png)

4.結果

![2022-09-22-09-53-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/8bffb81c-b7a9-93cd-a72e-c3fb4683163b.png)


#### 取り込み済みの場合での再実行の確認と追加

1.停止して再実行

![2022-09-22-09-53-54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/e9aaa24f-7a02-162d-116c-c17ef60d5398.png)

![2022-09-22-09-54-51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/6e6288c7-4fcf-8bfd-7bd9-4f1a93bb121f.png)


すでに読み込み済みなので増えません

![2022-09-22-09-54-41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/9cf32ef2-d798-6bf6-806f-80163bff1b00.png)


2.ファイル追加

![2022-09-22-09-56-12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/d15c91de-2824-fd3f-33d3-07946501da39.png)


3.セル実行が有効な間自動追加されていることを確認

![2022-09-22-09-56-04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/d37caae3-2b48-62e2-d7e8-25d582601afb.png)


4.さらに追加

![2022-09-22-09-56-26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/d8a17a91-dedc-2d6c-20ff-f4f452934056.png)


![2022-09-22-09-56-39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/6986a6dc-dfe4-df2b-323b-6fc167d00e2c.png)


#### Unity Catalog上の履歴

![2022-09-22-10-00-33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/97379f51-cfa1-b9af-00fa-181d30aae3b9.png)