Microsoft Purview Data Governance で Snowflake のオブジェクトやリネージ情報などのメタデータを抽出する

## はじめに

Purview Data Governance の Data Map は様々なテクニカルメタデータを収集します。
その対象に Snowflake のメタデータがあるので実際にやってみます。

## 参考

- https://learn.microsoft.com/ja-jp/purview/register-scan-snowflake


## 準備

試用版の snowflake にサインアップして、以下のようにサンプルクエリに少し手を加えたスクリプトを実行します。

```sql:sql
/*--
Tasty Bytes is a fictitious, global food truck network, that is on a mission to serve unique food options with high
quality items in a safe, convenient and cost effective way. In order to drive forward on their mission, Tasty Bytes
is beginning to leverage the Snowflake Data Cloud.

Within this Worksheet, we will walk through the end to end process required to load a CSV file containing Menu specific data
that is currently hosted in Blob Storage.
--*/

-------------------------------------------------------------------------------------------
    -- Step 1: To start, let's set the Role and Warehouse context
        -- USE ROLE: https://docs.snowflake.com/en/sql-reference/sql/use-role
        -- USE WAREHOUSE: https://docs.snowflake.com/en/sql-reference/sql/use-warehouse
-------------------------------------------------------------------------------------------

/*-- 
    - To run a single query, place your cursor in the query editor and select the Run button (⌘-Return).
    - To run the entire worksheet, select 'Run All' from the dropdown next to the Run button (⌘-Shift-Return).
--*/

---> set the Role
USE ROLE accountadmin;

---> set the Warehouse
USE WAREHOUSE compute_wh;

-------------------------------------------------------------------------------------------
    -- Step 2: With context in place, let's now create a Database, Schema, and Table
        -- CREATE DATABASE: https://docs.snowflake.com/en/sql-reference/sql/create-database
        -- CREATE SCHEMA: https://docs.snowflake.com/en/sql-reference/sql/create-schema
        -- CREATE TABLE: https://docs.snowflake.com/en/sql-reference/sql/create-table
-------------------------------------------------------------------------------------------

---> create the Tasty Bytes Database
CREATE OR REPLACE DATABASE tasty_bytes_sample_data;

---> create the Raw POS (Point-of-Sale) Schema
CREATE OR REPLACE SCHEMA tasty_bytes_sample_data.raw_pos;

---> create the Raw Menu Table
CREATE OR REPLACE TABLE tasty_bytes_sample_data.raw_pos.menu
(
    menu_id NUMBER(19,0),
    menu_type_id NUMBER(38,0),
    menu_type VARCHAR(16777216),
    truck_brand_name VARCHAR(16777216),
    menu_item_id NUMBER(38,0),
    menu_item_name VARCHAR(16777216),
    item_category VARCHAR(16777216),
    item_subcategory VARCHAR(16777216),
    cost_of_goods_usd NUMBER(38,4),
    sale_price_usd NUMBER(38,4),
    menu_item_health_metrics_obj VARIANT
);

---> confirm the empty Menu table exists
SELECT * FROM tasty_bytes_sample_data.raw_pos.menu;

---> create stream for cdc 
CREATE OR REPLACE STREAM stream_menu on table tasty_bytes_sample_data.raw_pos.menu

---> create the Stage referencing the Blob location and CSV File Format
CREATE OR REPLACE STAGE tasty_bytes_sample_data.public.blob_stage
url = 's3://sfquickstarts/tastybytes/'
file_format = (type = csv);



---> create view

CREATE OR REPLACE VIEW v_FreezinePoint_menu AS 
    SELECT *,(sale_price_usd - cost_of_goods_usd) AS profit_usd 
    FROM tasty_bytes_sample_data.raw_pos.menu 
    WHERE truck_brand_name = 'Freezing Point'

---> create proc

CREATE OR REPLACE PROCEDURE GET_TOP_SALES()
RETURNS TABLE (MENU_ITEM_NAME VARCHAR, PROFIT_USD NUMBER)
LANGUAGE SQL
EXECUTE AS CALLER
AS
DECLARE
  RES RESULTSET DEFAULT (
  SELECT 
   MENU_ITEM_NAME,
   (SALE_PRICE_USD - COST_OF_GOODS_USD) AS PROFIT_USD
    FROM TASTY_BYTES_SAMPLE_DATA.RAW_POS.MENU
    ORDER BY PROFIT_USD DESC LIMIT 10
    );
BEGIN
  RETURN TABLE(RES);
END;


CREATE OR REPLACE PROCEDURE COPY_INTO_MENU()
RETURNS VARCHAR NOT NULL
LANGUAGE SQL
AS
BEGIN
    COPY INTO TASTY_BYTES_SAMPLE_DATA.RAW_POS.MENU
    FROM @TASTY_BYTES_SAMPLE_DATA.PUBLIC.BLOB_STAGE/raw_pos/menu/;

    RETURN 'Rows inserted: ' || SQLROWCOUNT;
    
END;


---> run

CALL COPY_INTO_MENU();
CALL GET_TOP_SALES();

---> check changes 

SELECT * FROM stream_menu

```

以下のようにいくつかのオブジェクトが作成できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/a157d8c6-d464-7429-543d-0e7dbb8382be.png)


次に、[スキャンに必要なアクセス許可](https://learn.microsoft.com/ja-jp/purview/register-scan-snowflake#required-permissions-for-scan) を参考に Purview からの参照用ユーザーを作成します。

stream に対しての権限が付与されてなかったので追加

```sql:sql

GRANT SELECT ON ALL  STREAMS IN DATABASE TASTY_BYTES_SAMPLE_DATA TO role purview_reader;
GRANT SELECT ON FUTURE STREAMS IN DATABASE TASTY_BYTES_SAMPLE_DATA TO role purview_reader;

```


## Purview Data Map によるメタデータの抽出

### ソース登録～スキャンの作成・実行

まずはスキャン対象の Snowflake を登録します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/819d57e4-e897-895f-af3a-67ab5164162e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/ecf3efc8-e512-2e7a-18cc-4c0ade1f61d2.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/3d3377f3-f365-1fb1-9292-0dceb121bdd6.png)

登録後、スキャンを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/6440343d-2927-4992-7958-830a7e535523.png)

作成時に[資格情報がなければ作成](https://learn.microsoft.com/ja-jp/purview/manage-credentials) します。現在のところ基本認証のみが対応しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/21ab5500-0cb3-fc42-d801-7ce12aec004b.png)

資格情報では、以下のように パスワードを記録した Key Vault シークレット名を指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/f41f3b70-6679-8836-a62d-03eec2a5b9c9.png)

secret を作成します。
なお、事前に Purview にはKey Vault へのシークレット利用権限（Secret User 等のロール）が必要です

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/3367b915-4454-3e5f-c971-c092dda60ade.png)


残りの情報を入力したらこの接続をテストします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/cadd1ead-989d-63fa-8e22-721e644803d4.png)


:::note info

ストアドプロシージャの系列取得には追加の設定があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/ae65128f-b139-e836-5479-44872dd6fbf2.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/94fdf73d-6d79-d6c5-7172-04258aee7fd9.png)
https://learn.microsoft.com/ja-jp/purview/register-scan-snowflake#create-and-run-scan

:::

ここまでの設定ができていれば、テスト接続が成功します。

:::note warn

データベース名などは大文字小文字の違いにより動作しないことがあるのでうまくいかない場合はそのあたりを疑ってみましょう

:::


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/f3c01e18-5b65-d933-984b-badfa375607f.png)

[データの分類規則](https://learn.microsoft.com/ja-jp/purview/supported-classifications)などが定義されたスキャンルールセットを選択し、一度だけのスキャン実行を構成したら保存・実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/0429398e-7590-8867-87b1-0a0795378b1e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/4919140f-aa2f-c927-ce41-fb4fdcb20dec.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/48e50733-a41c-910f-a5d0-afdb0880bf88.png)


しばらく待つと、スキャンと取り込みが成功しました。




### テクニカルメタデータの確認

スキャン結果を確認していきます。

10件が取り込まれています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/1cb4ac12-b47f-0e98-a928-f39faaba2a4b.png)

まずは基本となるテーブル。分類され、住所を含むテーブルと認識されたようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/98335572-2feb-33cc-7f4b-0b5fb4b99e5f.png)

列項目

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/fd8b71f1-8022-077d-35fe-5d64e8f44fa5.png)

リネージでは、stored procedure , view および stream と接続され、PROFIT_USD が SALE_PRICE_USD と関連をもつことがわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/f432ab1e-597b-26ec-d4bf-f6d6eb591e82.png)

:::note info

ストアドのリネージはオブジェクトの大文字小文字を区別しているようでした。
小文字で テーブル名を書いてたりするとリネージに記録されず、少し苦戦しました。

:::



最後に、COPY 句のストアドの場合にリネージが取れてませんでした。対応しているステートメントには制限があるのかも

COPY_INTO_MENU

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/2961bb0d-ed78-59a6-6507-4330157a5ee0.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/0948f765-0eb3-e047-486b-c08b1051943c.png)