Slide 1

Slide 1 text

#pyconjp_5 SQLクエリ解析による E2Eデータリネージの実現 PyCon JP 2022 2022-10-15(Day2) $ stairlight up -t your_table

Slide 2

Slide 2 text

#pyconjp_5 堤 利史 Toshifumi Tsutsumi @tosh2230 Data Engineer GMO Pepabo, inc. #風来のシレン #原神 2 自己紹介

Slide 3

Slide 3 text

#pyconjp_5 3 PyCon JP 2021 ありがとうございました! https://speakerdeck.com/tosh2230/introduction-to-python-logg ing-9744df54-fd32-476c-aae2-88ef948ba522

Slide 4

Slide 4 text

#pyconjp_5 このスライドは公開されています 4 https://docs.google.com/presentation/d/1aDdmUuFc3vxJn 2IAkAK5vMuDEVYxorayByHqhJDpQ8A

Slide 5

Slide 5 text

#pyconjp_5 このトークで話すこと 5 [ ] データリネージとはなにか [ ] なぜSQLなのか [ ] E2Eの範囲はどこまでか [ ] Pythonでどのように実現するのか [ ] どのように運用するのか SQLクエリ 解析による E2E データリネージ の実現

Slide 6

Slide 6 text

#pyconjp_5 1. データリネージの概要 2. 導入のハードルを下げるために 3. Python製OSS: Stairlight 4. 他のソフトウェアと組み合わせる 5. まとめ 6 Contents

Slide 7

Slide 7 text

#pyconjp_5 1. データリネージの概要 2. 導入のハードルを下げるために 3. Python製OSS: Stairlight 4. 他のソフトウェアと組み合わせる 5. まとめ 7 Contents

Slide 8

Slide 8 text

#pyconjp_5 データリネージ(Data lineage)とは 8 データの系譜を明らかにすること lineage: 血統、家柄 データ活用の場面で使われる メタデータ(データを説明するためのデータ)の一種 注: このトークにおける用語の定義は下記とします - データ: データリネージの対象 - データイベント: データに対するCRUDの総称 - リネージ情報: データリネージによって得られる情報

Slide 9

Slide 9 text

#pyconjp_5 データリネージが解決したい課題 1 データの可観測性(Data observability)の向上 このデータは何から生まれたのか? = 問題が起きたとき、どこを辿ればよいのか このデータはどこで使われているのか? = 問題が起きたとき、どこに影響するのか これらを、いつでも誰でもわかるようにしたい! 9

Slide 10

Slide 10 text

#pyconjp_5 データリネージが解決したい課題 2 10 持続可能なドキュメンテーションの難しさ データは様々な場所・タイミングで作られ、使われるもの 人間、アプリケーション、ダッシュボード、機械学習モデル... 多くの人・ものが関わり、その範囲が広いほど、 データが ”いま” どのように作られ、使われているのかを ドキュメント化するのは難しい

Slide 11

Slide 11 text

#pyconjp_5 データリネージ手法の分類 11 何をもとにリネージ情報をつくるか?で分類してみる - データイベント - データイベントのログ - データイベント関連のソースコード - 上記いずれかの複合型

Slide 12

Slide 12 text

#pyconjp_5 データリネージ手法の分類: データイベント 12 データイベントをトリガーにリネージ情報を作成 Open Lineage*1 データリネージ フレームワーク 収集用 API を設けて、 データイベントを起きたときに リクエストを送信してもらう Marquez*2 Open Lineage に則って 作成したリネージ情報を蓄積して可視化 図は https://openlineage.io/ より引用 *1 https://openlineage.io/ *2 https://github.com/MarquezProject/marquez

Slide 13

Slide 13 text

#pyconjp_5 データリネージ手法の分類: データイベントのログ 13 データイベントのログに含まれる情報から リネージ情報をつくる Google BigQuery の 監査ログとその他サービスを 組み合わせた例 図は Use business metadata tool Data Catalog to create tagged data lineage | Google Cloud Blog より引用

Slide 14

Slide 14 text

#pyconjp_5 データリネージ手法の分類: データイベント関連のソースコード 14 ソースコードやSQLを解析して、リネージ情報を作成 reata/sqllineage* 入力したSQL文のテーブルや列のつながりを見つける グラフ表示機能あり * https://github.com/reata/sqllineage

Slide 15

Slide 15 text

#pyconjp_5 データリネージ手法の分類: 複合型 15 Transform*1 専用ツールの1機能としてデータリネージを提供 dbt https://www.getdbt.com/ Dataform https://dataform.co/ Data observability を軸にしたサービス・ソフトウェア Atlan https://atlan.com/ Monte Carlo Data https://www.montecarlodata.com/ OpenMetadata https://docs.open-metadata.org/ * データ構造を組み替えること。一般に Extract, Transform, Load の工程をまとめて ETLと呼びます

Slide 16

Slide 16 text

#pyconjp_5 データリネージとは? まとめ 16 データリネージとは、データの系譜を明らかにすること 目的は主に2つある - データの可観測性(Data observability)の向上 - 持続可能なドキュメンテーション 生成元を何にするかによって、実現方法は複数ある

Slide 17

Slide 17 text

#pyconjp_5 このトークで話すこと 17 [✔] データリネージとはなにか [ ] なぜSQLなのか [ ] E2Eの範囲はどこまでか [ ] Pythonでどのように実現するのか [ ] どのように運用するのか SQLクエリ 解析による E2E データリネージ の実現

Slide 18

Slide 18 text

#pyconjp_5 1. データリネージの概要 2. 導入のハードルを下げるために 3. Python製OSS: Stairlight 4. 他のソフトウェアと組み合わせる 5. まとめ 18 Contents

Slide 19

Slide 19 text

#pyconjp_5 データリネージ事情を調べていて思ったこと 19 OSS がたくさんあってありがたい... 多機能で便利、やってみたい! ただ、新規システムの導入や既存アーキテクチャの変更は 大変になりがち... 手軽に試せる方法はないのだろうか?

Slide 20

Slide 20 text

#pyconjp_5 “手軽に試せる” に求められる要素 20 既存の資産をそのまま活用できる ソフトウェア・ツールは現在のものを使い続ける 追加で必要となるコストは抑えめ データソースへのアクセス権限はそのまま(攻撃対象領域を限定) 独立性が高い(=結合度が低い) 特定の機能・仕様への依存を控える はじめやすく、捨てやすい インターフェースが汎用的である 長年使われていて利用者が多い 抽象度が高い ← まずはここから考え始めた

Slide 21

Slide 21 text

#pyconjp_5 SQLはどうだろうか? 21 リレーショナルデータベース管理システム(RDBMS)の問い合わせ言語 技術の変化が激しい中、長年使われ続けているインターフェース sqllineage でも採用されている 加えて、近年 SQL の利用シーンが広がっている

Slide 22

Slide 22 text

#pyconjp_5 SQL関連の3つの動き 22 1. RDBMS以外での利用 2. SQLをテンプレートからコンパイル 3. Transform を CREATE TABLE AS SELECT で行う

Slide 23

Slide 23 text

#pyconjp_5 動き1: RDBMS以外での利用 23 列指向データベースへの問い合わせ言語 BigQuery documentation | Google Cloud Amazon Redshift SQL Key-Value Store への問い合わせ言語 PartiQL - a SQL-compatible query language for Amazon DynamoDB GQL Reference | Cloud Datastore Documentation

Slide 24

Slide 24 text

#pyconjp_5 動き1: RDBMS以外での利用 24 分散処理 Apache Hive Apache Spark SQL Trino(Presto) データパイプラインの構築 Quickstart: Create a Dataflow pipeline using SQL | Google Cloud 機械学習モデルの学習と推論 What is BigQuery ML? | Google Cloud Redshift ML - Amazon Web Services

Slide 25

Slide 25 text

#pyconjp_5 動き2: SQLをテンプレートからコンパイル: dbt 25 https://docs.getdbt.com/guides/getting-started/learning-more/using-jinja#set-variabl es-at-the-top-of-a-model より引用 # SQL に Jinja template が埋め込まれている {%- set payment_methods = ["bank_transfer", "credit_card", "gift_card"] -%} select order_id, {%- for payment_method in payment_methods %} sum(case when payment_method = '{{payment_method}}' then amount end) as {{payment_method}}_amount {%- if not loop.last %},{% endif -%} {% endfor %} from {{ ref('raw_payments') }} group by 1

Slide 26

Slide 26 text

#pyconjp_5 動き3: Transform を CREATE TABLE AS SELECT で行う 26 データウェアハウスのコンピューティング能力向上 and コスト低下により、 Transform をデータウェアハウスで行うことが容易になった CREATE TABLE AS SELECT で Transform を行う場合、 クエリ実行後の抽出結果がそのままテーブル*になる この場合、SELECT 文はテーブルを説明する情報 といえる * ビューやマテリアライズドビューという選択肢もあります

Slide 27

Slide 27 text

#pyconjp_5 27 すべてがSQLになる(要出典) SQL は、データの生成・収集・加工・利用という一連のライフサイクルを 表現できる汎用的な言語になりつつある SQL をインターフェースとして、データリネージを実現できないか?

Slide 28

Slide 28 text

#pyconjp_5 SQL を見つけて、解析した結果をすべて繋ぎ合わせると データライフサイクル全体をカバーする E2E データリネージができるはず コンセプト 28

Slide 29

Slide 29 text

#pyconjp_5 さらに抽象化してみる 29

Slide 30

Slide 30 text

#pyconjp_5 残った2つの要素を考える 既存の資産をそのまま活用できる ソフトウェア・ツールは現在のものを使い続ける 追加で必要となるコストは抑えめ データソースへのアクセス権限はそのまま(攻撃対象領域を限定) 独立性が高い(=結合度が低い) 特定の機能・仕様への依存を控える はじめやすく、捨てやすい 30

Slide 31

Slide 31 text

#pyconjp_5 リネージ情報の抽出に特化する 31 SELECT 文を解析するが、クエリとして実行しない よって、クエリが発行される対象へのアクセス権限はつけなくてよいので、 ネットワーク構成やセキュリティ基準は変更なし この方式であれば、既存の資産をそのまま活用できる

Slide 32

Slide 32 text

#pyconjp_5 小さく、他のコンポーネントに影響を与えない 独立性の高いエージェントとしてふるまう 抽出処理の手数を少なくする 設定や出力はファイルで保持する 抽出工程をできるかぎり簡単にする 32

Slide 33

Slide 33 text

#pyconjp_5 このトークで話すこと 33 [✔] データリネージとはなにか [✔] なぜSQLなのか [✔] E2Eの範囲はどこまでか [ ] Pythonでどのように実現するのか [ ] どのように運用するのか SQLクエリ 解析による E2E データリネージ の実現

Slide 34

Slide 34 text

#pyconjp_5 1. データリネージの概要 2. 導入のハードルを下げるために 3. Python製OSS: Stairlight 4. 他のソフトウェアと組み合わせる 5. まとめ 34 Contents

Slide 35

Slide 35 text

#pyconjp_5 https://github.com/tosh2230/stairlight 35 An end-to-end data lineage tool, detects table dependencies from SQL statements.

Slide 36

Slide 36 text

#pyconjp_5 特徴 36 Python 製のデータリネージ OSS MIT License PyPI で公開中。 $ pip install stairlight SQLをもとにしたリネージ情報の抽出に特化 SELECT 文を含む SQL 文字列をデータリネージの対象にできる JSON 文字列を標準出力へ流す コマンドとしても、ライブラリとしても利用可

Slide 37

Slide 37 text

#pyconjp_5 なぜ Python を選んだのか 37 データ分析領域でよく利用されている言語 ビジュアライズ系のフレームワーク、ライブラリが充実 リネージ情報の抽出に特化する → グラフ表示は他を頼る テンプレート SQL で jinja2*1 が使われているケースが見られる - dbt - Apache Airflow*2 : Python製のワークフローエンジン *1 https://jinja.palletsprojects.com/en/3.1.x/ *2 https://airflow.apache.org/

Slide 38

Slide 38 text

#pyconjp_5 前提: SELECT クエリの実行結果 → ”テーブル”と表現 38 SELECT 文はテーブルを説明する情報である このトークでは、SELECT クエリによる抽出結果* のような 表形式であらわせるデータ全般 を便宜上 “テーブル” と表現します データベースにおける永続テーブル、一時テーブル 出力ファイル インメモリデータなど * Stairlight はクエリを発行しないので、正確には「発行した場合に抽出されるデータ」を指します

Slide 39

Slide 39 text

#pyconjp_5 : テーブル : 参照 データパイプラインは 上流から下流へデータが流れていく グラフ構造*1を成していると考える Stairlight は、このグラフの ノード(テーブル)と エッジ(テーブル間の参照関係)を見つける*2 データのつながりを見つける select … from … select … from … select … from … select … from … select … from … select … from … left join … on … 39 *1 同一テーブルに対する複数箇所での参照や、自身への参照がありうるため、正確には有向多重グラフです。 *2 Stairlight(階段灯)は、テーブル のどこに 参照関係 があるのかを知らせる役割をもちます 風来のシレン5 の”ドコ?カイ弾”です フロア 階段

Slide 40

Slide 40 text

#pyconjp_5 下記に保存されている、SELECT 文を含む文字列を解析対象にできる データソース サポート対象 40 データソース DataSource Type 補足情報 ローカルファイル File Pathlib を使用 Amazon S3 S3 Amazon Managed Workflows for Apache Airflow(MWAA) も対応可 Google Cloud Storage GCS Google Cloud Composer も対応可 dbt dbt `dbt compile` した結果を解析 現時点では Google BigQuery のみ対応 Redash Redash 現時点では Saved query のみ対応

Slide 41

Slide 41 text

#pyconjp_5 データリネージを3ステップで行う 41 1. データソースの指定 2. SQL 文とテーブル名称のマッピング 3. リネージ情報の出力

Slide 42

Slide 42 text

#pyconjp_5 Step1: データソースの指定 42 $ stairlight init stairlight.yaml の雛形をつくる このファイルで検出対象・対象外とするデータソースを指定する “TemplateSourceType” でデータソースの種類を指定(File, GCS など)

Slide 43

Slide 43 text

#pyconjp_5 Step1: データソースの指定 # stairlight.yaml サンプル Include: # 抽出対象の条件 - TemplateSourceType: File # データソース種別 FileSystemPath: "./tests/sql" # 抽出対象とするパス Regex: ".*/*.sql$" # 抽出対象とするファイル(正規表現) DefaultTablePrefix: "PROJECT_A" # テーブル名称のデフォルトPrefix Exclude: # 抽出対象外の条件 - TemplateSourceType: File Regex: "main/exclude.sql$" Settings: MappingPrefix: "mapping" # マッピング設定ファイルの名称 43

Slide 44

Slide 44 text

#pyconjp_5 Step2: SQL 文とテーブル名称のマッピング 44 $ stairlight map mapping.yaml の雛形をつくる mapping.yaml では、SELECT 文とテーブル名称のマッピングを行う データソースから SELECT 文を読み取って、Jinja variables を探す すでに mapping.yaml があれば、未設定のパラメータだけを抽出する この時点ではリネージ情報は生成していない

Slide 45

Slide 45 text

#pyconjp_5 Jinja templating SQL 文にある Variables に対して、mapping.yaml でパラメータを 複数設定していれば、その数だけ SQL 文が存在するものとみなす 45 Mapping: - TemplateSourceType: GCS Uri: "gs://stairlight/sql/sample_02.sql" Tables: - TableName: "PROJECT_A.DATASET_B.TABLE_D" Parameters: DESTINATION_TABLE: TABLE_D - TableName: "PROJECT_A.DATASET_B.TABLE_E" Parameters: DESTINATION_TABLE: TABLE_E sample_02.sql (TABLE_D) sample_02.sql (TABLE_E)

Slide 46

Slide 46 text

#pyconjp_5 Step3: リネージ情報の出力 46 $ stairlight stairlight.yaml と mapping.yaml が揃っている状態で実行すると 検出したリネージ情報をメモリに蓄積して、JSON 文字列として まとめて標準出力する mapping.yaml にあるパラメータを適用しつつ、SQL文を コンパイルしてから読み込む

Slide 47

Slide 47 text

#pyconjp_5 リネージ情報のデータ構造 抜粋 47 { "PROJECT_A.DATASET_B.TABLE_C": { # テーブル名称 "PROJECT_A.DATASET_B.TABLE_D": { # 上流テーブル名称 "TemplateSourceType": "File", # タイプ "Key": "sql/sample_01.sql", "Uri": "/foo/bar/stairlight/sql/sample_01.sql", # SQLがある場所 "Lines": [{ # SQLでの参照箇所 "LineNumber": 6, "LineString": " PROJECT_A.DATASET_B.TABLE_D" }] } } } TABLE_D TABLE_C

Slide 48

Slide 48 text

#pyconjp_5 リネージ情報の保存*1 $ stairlight --save results/20221015.json リネージ情報の読み込み*2 $ stairlight --load results/20221015.json 読み込みファイルを複数指定すると、リネージ情報をマージする $ stairlight --load a.json --load b.json --save c.json リネージ情報の保存と読み込み 48 *1 ローカルのほか、S3 や GCS へも出力可 *2 load オプションを指定した場合、データソースへのアクセスはしない

Slide 49

Slide 49 text

#pyconjp_5 リネージ情報の収集と統合 49 各所で抽出した結果を 一箇所に集めてから統合 : Read : Write

Slide 50

Slide 50 text

#pyconjp_5 依存関係をもつテーブルの検索 50 table_name から見て ひとつ(上|下)に位置するテーブルを検索 $ stairlight (up|down) -t table_name table_name が直接的もしくは間接的に依存しているテーブルを 再帰的に検索 $ stairlight up -t table_name -r table_name に対して、直接的もしくは間接的に依存しているテーブルを 再帰的に検索 $ stairlight down -t table_name -r

Slide 51

Slide 51 text

#pyconjp_5 51 実装の一部をご紹介

Slide 52

Slide 52 text

#pyconjp_5 YAML 設定値は Dataclass に格納 # src/stairlight/source/file/config.py から一部抜粋 # stairlight.yaml の Include セクションで TemplateSourceType が File の場合 @dataclass class StairlightConfigIncludeFile(StairlightConfigInclude): TemplateSourceType: str = source_type.FILE.value FileSystemPath: str | None = None Regex: str | None = None DefaultTablePrefix: str | None = None 52

Slide 53

Slide 53 text

#pyconjp_5 SQL 文からの Jinja variables 検出 53 # src/stairlight/source/template.py から一部抜粋 # 正規表現で頑張っている @staticmethod def detect_jinja_params(template_str: str) -> list: jinja_expressions = "".join( re.findall("{{[^}]*}}", template_str, re.IGNORECASE) ) return re.findall("[^{} ]+", jinja_expressions, re.IGNORECASE)

Slide 54

Slide 54 text

#pyconjp_5 未設定パラメータの検出 54 # src/stairlight/map.py から一部抜粋 # set 型の差集合で重複除去 def detect_unmapped_params( self, template: Template, table_attributes: MappingConfigMappingTable ) -> list[str]: (中略) unmapped_params: list[str] = list( set(template_params) - set(mapped_params) - set(ignore_params) ) return unmapped_params

Slide 55

Slide 55 text

#pyconjp_5 リネージ情報の保持と検索 55 リネージ情報は、プログラムの中では dict で保持している Key: 下流のテーブル名称 Value: 上流のテーブル名称と、その検出位置の情報 テーブル名称によるリネージ情報の検索を速くするため テーブル数は多くても数百〜数千のオーダーであると想定したので データベースを用意しない構成を選択

Slide 56

Slide 56 text

#pyconjp_5 再帰的な探索におけるテーブル循環検出 56 例えば、テーブルA と テーブルA’をマージして テーブルA としてつくりなおすケースを考える “テーブルAに依存するテーブル”を再帰的に探索すると(-r オプション) RecursionError が発生するまで頑張ってしまうので、打ち切りたい こういうことなのだが リネージ情報では循環表現になる TABLE_A (new) TABLE_A' TABLE_A (old) TABLE_A TABLE_A'

Slide 57

Slide 57 text

#pyconjp_5 フロイドの循環検出法 57 任意の数列に対する循環検出アルゴリズム 再帰的な探索の都度、これまで検出したテーブルを 単方向連結リストにして、循環が発生していないかチェックする リストの先頭から同時に動き出す “fast” と “slow” を考える fast: 一度に2つ進む slow: 一度に1つ進む 先を進んでいるはずの fast が slow に追いついたら そのリストは循環しているので、探索処理を打ち切る https://github.com/tosh2230/stairlight/blob/37a8a5da0b04dbf24dcffc26e485cbbff90 c9881/src/stairlight/stairlight.py#L513-L539

Slide 58

Slide 58 text

#pyconjp_5 このトークで話すこと 58 [✔] データリネージとはなにか [✔] なぜSQLなのか [✔] E2Eの範囲はどこまでか [✔] Pythonでどのように実現するのか [ ] どのように運用するのか SQLクエリ 解析による E2E データリネージ の実現

Slide 59

Slide 59 text

#pyconjp_5 1. データリネージの概要 2. 導入のハードルを下げるために 3. Python製OSS: Stairlight 4. 他のソフトウェアと組み合わせる 5. まとめ 59 Contents

Slide 60

Slide 60 text

#pyconjp_5 $ stairlight | less $ stairlight | jq '.["PROJECT_d.DATASET_e.TABLE_f"][] \ | select(.TemplateSourceType == "File")' Stairlight がローカルにインストールされていれば、 コマンドを実行してリネージ情報を見ることができる 影響調査や設計のときにさっと確認するのに便利 Pipe でつないで別のコマンドへ流すことも可能 Shell でのコマンド実行 60

Slide 61

Slide 61 text

#pyconjp_5 Git による履歴管理 61 データの流れは日々変化していく(特に参照)ので、その変化を 時系列的に追跡できると調査を行うときに便利 変更があったタイミングとその内容を Git で記録する ファイルベースのシンプルな構成だからできること

Slide 62

Slide 62 text

#pyconjp_5 設定用のファイル、特に mapping.yaml の内容は データソースの更新に追従している状態を保つことが望ましい たとえば、アプリケーションリポジトリ main branch への Pull Request マージをトリガーにリネージ情報を更新する 持続可能なドキュメンテーションの難しさという課題の解決を試みる リネージ情報を最新に保つ 62

Slide 63

Slide 63 text

#pyconjp_5 CI/CD サービスによる継続的なデータリネージ案 63 アプリケーション、データリネージ それぞれの別々に リポジトリがあるとする 下記の処理を CI/CD サービスで行う 1. stairlight map コマンドで未設定パラメータを検出 2. stairlight --load オプション複数指定によって 既存の mapping.yaml とマージ 3. Pull Request 作成 アプリケーションの Pull Request と データリネージの Pull Request が紐づいて便利なのでは !?

Slide 64

Slide 64 text

#pyconjp_5 もう一つの課題、データの可観測性の向上 これに対しては、アプリケーションに Stairlight を Python ライブラリとして組み込むことで対応 クラス関数の使い勝手は、コマンドと(だいたい)同じ アプリケーションへの組み込み 64 コマンド 対応するクラス関数 stairlight StairLight.create_map() stairlight up StairLight.up() stairlight down StairLight.down()

Slide 65

Slide 65 text

#pyconjp_5 Streamlit 65 Web アプリケーションを Python で手軽に実装できる手段として Streamlit*1 がある UI のコントロールやその入力値の取得を直感的に実装できる 次のスライドで、graphviz*2, Stairlight を使って リネージ情報をグラフ表示するサンプルアプリケーションを紹介 *1 https://streamlit.io/2 *2 https://github.com/xflr6/graphviz

Slide 66

Slide 66 text

#pyconjp_5 tosh2230/stairlight-app 66 https://stairlight.run/

Slide 67

Slide 67 text

#pyconjp_5 リネージ情報はマスタデータ リネージ情報は、データライフサイクルの全体像を表す マスタデータとして位置づけられる データイベントに関する各種ログは、トランザクションデータとして扱い アプリケーション上で組み合わせる 67

Slide 68

Slide 68 text

#pyconjp_5 リネージ情報との組み合わせ例 68 組み合わせは無限大! 組み合わせるもの 見れるもの (なし) リネージグラフ データカタログ テーブルごとのメタデータ (例: データオーナーやテーブル定義) データ参照ログ データ利用状況 事業におけるクリティカルパスはどこか 利用されていない経路はないか データ更新ログ データ更新遅延の有無

Slide 69

Slide 69 text

#pyconjp_5 このトークで話すこと 69 [✔] データリネージとはなにか [✔] なぜSQLなのか [✔] E2Eの範囲はどこまでか [✔] Pythonでどのように実現するのか [✔] どのように運用するのか SQLクエリ 解析による E2E データリネージ の実現 💮

Slide 70

Slide 70 text

#pyconjp_5 1. データリネージの概要 2. 導入のハードルを下げるために 3. Python製OSS: Stairlight 4. 他のソフトウェアと組み合わせる 5. まとめ 70 Contents

Slide 71

Slide 71 text

#pyconjp_5 本日のおさらい 71 Stairlight は、データライフサイクル全般に対する - データの可観測性の向上 - 持続可能なドキュメンテーション を実現するための基礎となるツールで、 データリネージ導入のハードルを下げるために開発しました 周辺エコシステムとの組み合わせで力を発揮します

Slide 72

Slide 72 text

#pyconjp_5 今後の展望 72 - 継続的なリネージ情報の更新について、具体的な実装例の追加 - データソースの拡充 - sqlparse*1 の導入 SQL をトークンレベルで解析して情報量を増やす - カラムリネージの実現 テーブルリネージ情報からドリルダウンして、列同士の関係性を把握 sqlparse とテーブル定義情報*2 を組み合わせれば実装できるはず... *1 https://github.com/andialbrecht/sqlparse *2 SELECT 文でアスタリスクを使用しているときに必要になりそう

Slide 73

Slide 73 text

#pyconjp_5 データリネージの普及を目指して 73 皆様の力をお借りすることで、さらによいものにしていきたい! ぜひフィードバックいただけるとうれしいです @tosh2230 tosh2230/stairlight

Slide 74

Slide 74 text

#pyconjp_5 SQLスクリプト上でのテーブルや共通テーブル式の依存関係を可視化する, Dentsu Digital Tech Blog Overview of The Modern Data Stack / モダンデータスタック概論, Satoshi Hirose, Speaker Deck フロイドの循環検出法, Wikipedia Python最新バージョン対応!より良い型ヒントの書き方, 寺田学, Gihyo.jp 参考資料 74

Slide 75

Slide 75 text

#pyconjp_5 75 Thank you!

Slide 76

Slide 76 text

#pyconjp_5 76 (Appendix) PyPI パッケージの 開発・管理方法

Slide 77

Slide 77 text

#pyconjp_5 下記のパッケージを使って開発 CI に組み込んでいるため、Push するたびに起動 flake8*1 : Linter black*2 : Formatter isort*3 : Import の順番をソート Linter, Formatter 77 *1 https://github.com/pycqa/flake8 *2 https://github.com/psf/black *3 https://github.com/PyCQA/isort

Slide 78

Slide 78 text

#pyconjp_5 Type hints 78 型ヒント*1 可読性の向上 IDEでのコード自動補完 mypy*2 による静的型チェック ユニットテストではカバーしきれなかった型の整合性を チェックできるようになった これも CI に組み込んでいる *1 https://docs.python.org/3/library/typing.html *2 https://github.com/python/mypy

Slide 79

Slide 79 text

#pyconjp_5 CI では、複数のPython バージョンを対象にユニットテスト pytest*1 79 *1 https://docs.pytest.org/en/7.1.x/ *2 https://pytest-cov.readthedocs.io/en/latest/ pytest-cov*2 によるカバレッジ計測

Slide 80

Slide 80 text

#pyconjp_5 パッケージ依存管理とパッケージングを行うツール 仮想環境の作成によって開発環境を分離 Linter や Formatter, Unit test の諸設定をまとめられる パッケージのアーカイブ作成やビルドを行う build コマンド、 PyPI への publish コマンドが便利 Poetry* でのパッケージ管理 80 * https://python-poetry.org/

Slide 81

Slide 81 text

#pyconjp_5 Extras でインストール対象を指定 Stairlight をインストールする時に Extras を指定しない場合 ローカルからの読み込みだけができる $ pip install stairlight 下記のようにインストールすると ローカル, S3, GCS からの読み込みができる $ pip install “stairlight[s3, gcs]” 81

Slide 82

Slide 82 text

#pyconjp_5 Extras でインストール対象を指定 82 # pyproject.toml から抜粋 # データソースごとに Extra を設定 [tool.poetry.extras] gcs = ["google-cloud-storage", "protobuf"] redash = ["psycopg2", "SQLAlchemy"] dbt-bigquery = [ "dbt-core", "dbt-bigquery", "google-cloud-bigquery", "protobuf", "networkx" ] s3 = ["boto3", "boto3-stubs"]