Microsoft Fabric OneLake を DuckDB で分析する

## はじめに

OneLakeはDelta Lakeを標準フォーマットとして採用しているため、3rd partyツールでの分析が可能です。

今回は、Delta Lakeへのサポートが追加されたDuck DBを使用することで、Fabricのコンピューティングエンジンを利用せずにSQL分析を実施してみます。Duck DBを使用することで、軽量かつ高速なSQL分析が可能となり、Fabricのリソースを節約できます。

## 参考

- https://duckdb.org/docs/extensions/delta.html
- https://duckdb.org/2024/06/10/delta.html
- https://github.com/djouallah/Fabric_Notebooks_Demo/blob/main/Attach_LH/Attach_Lakehouse_v2.ipynb

## 案1 azure Storage として接続する

構成イメージ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/d4f43550-62af-dd28-5f06-5df47c94f785.png)


### 手順

1. onelake 側の準備として、レイクハウス or ウェアハウス上のテーブルを作成し、プロパティから abfss パスを取得します。※今回はサンプルウェアハウスを使用
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/e1a5d4ba-ae84-37b4-fa0d-3a308c40c8a5.png)


1. 必要なモジュールをインストールします。
    ```python:python
    
    %pip install azure-identity
    %pip install  duckdb --upgrade
    
    ```
1. OneLake に接続するためのtoken取得
    ```python:python
    def get_token():
        from azure.identity import InteractiveBrowserCredential
        token = InteractiveBrowserCredential().get_token("https://storage.azure.com/.default")
        return token.token
    
    ```
    
    ```python:python
    token = get_token()
    ```
1. duck db からOneLake に接続確認
    ```python:python
    
    import time
    import duckdb
    
    con = duckdb.connect(f'temp_{time.time_ns()}.duckdb')
    con.sql('SET enable_object_cache=true')
    con.sql(f""" CREATE or replace SECRET onelake ( TYPE AZURE, PROVIDER ACCESS_TOKEN, ACCESS_TOKEN '{token}')   """)
    
    path="最初に取得したabfss パスを設定"
    con.sql(f"""SELECT COUNT(1) FROM delta_scan('{path}') """).show()
    
    ```
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/b1d01fef-d388-0675-dc4d-c33312fa9060.png)
1. duck db 上にビューを作成
    ```python:python
    
    def create_local_view(con,path,schema,table):
    
        con.sql(f"CREATE SCHEMA IF NOT EXISTS {schema};")
        con.sql(f"""CREATE OR REPLACE view {schema}.{table} AS SELECT * FROM delta_scan('{path}'); """)
    
    ```

    ```python:python
    
    create_local_view(con, path, "dbo", '"Trip"')
    
    ```
1. 分析クエリが実行できるようになります。

    ```python:python
    
    con.sql(""" SELECT [DateID],COUNT(1) as TripCount
    FROM dbo."Trip"
    GROUP BY [DateID]
    ORDER BY 2 DESC
     """) 
    
    ```
    
    
    ```
    ┌─────────────────────────┬───────────┐
    │ main.list_value(DateID) │ TripCount │
    │         int32[]         │   int64   │
    ├─────────────────────────┼───────────┤
    │ [20131101]              │      9985 │
    │ [20130511]              │      9953 │
    │ [20130426]              │      9765 │
    │ [20130302]              │      9681 │
    │ [20131004]              │      9656 │
    │ [20130111]              │      9503 │
    │ [20131212]              │      9456 │
    │ [20131011]              │      9449 │
    │ [20130315]              │      9431 │
    │ [20130502]              │      9411 │
    │     ·                   │        ·  │
    │     ·                   │        ·  │
    │     ·                   │        ·  │
    │ [20130121]              │      5484 │
    │ [20131128]              │      5243 │
    │ [20131226]              │      5149 │
    │ [20130902]              │      4858 │
    │ [20131225]              │      4776 │
    │ [20130704]              │      4667 │
    │ [20130803]              │      3707 │
    │ [20130802]              │      3609 │
    │ [20130804]              │      3291 │
    │ [20130811]              │      3279 │
    ├─────────────────────────┴───────────┤
    │ 365 rows (20 shown)       2 columns │
    └─────────────────────────────────────┘
    ```
    2.1 秒で応答しています。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/f7f5c401-0582-8ab0-bb43-1f9be310a170.png)


## 案2 local file として接続する

:::note warn

この方式は結論からいうと、空白を含むパスへの delta_scanが対応していないためにうまくいきませんでした。

:::


OneLake ファイルエクスプローラーを使用すると、OneLake 上の Delta Parquet を OneDrive のようにローカル環境に同期できます。
これを利用して、より簡単に DuckDB からローカル環境の Delta Parquet に接続してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/9a5dae1d-04c0-38bb-ac76-bd9290513c1f.png)

構成イメージ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/2ee13253-6ba9-882f-1486-e6fec3bee1d3.png)

### 手順

1. OneLake ファイルエクスプローラーから、対象のレイクハウス or ウェアハウスで、データを保持するように右クリック設定します。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/7166af55-54aa-664d-8c0a-6249f172e5e9.png)
2. 対象のテーブルフォルダのパスをコピーして、delta_scanで select します。・・・が、失敗。シンボリックリンクや、カレントディレクトリを変えたりしてみましたが、うまくいかず今回は供養までとします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/e3647adc-8f4c-a3c2-4458-abc88734a97f.png)