








フィールド分類 | | 説明 | 説明 |
サービス名 | | モデルサービスの一意の識別名です。 | 業務用途に応じた命名を推奨します。クリックしてサービス詳細ページへ移動できます。 |
サービス状態 | | サービス現在の実行ライフサイクル状態です。 | 一般的な状態には、草稿(起動中)、実行中、停止済みなどがあります。 |
サービスタイプ | | サービスが属するアプリケーション分野を識別します。 | 例:機械学習サービスです。 |
実行中バージョン/バージョン数 | | 現在アクティブなサービスバージョン/総バージョン数 | サービスグループのマルチバージョン管理状況を表示します。例えば0/1は、合計1バージョンが存在するが未起動であることを示します。 |
サービスグループの説明 | | このサービスグループに関する説明です。 | チーム間のコラボレーション時に、このサービスグループの用途をすばやく把握するのに役立ちます。 |
作成者 | | このサービスを作成したユーザーアカウントです。 | 監査および権限の追跡に使用されます。 |
作成時間 | | サービスが初めて作成された時間です。 | 時間順に並べ替えることができ、最近のサービスをすばやく見つけるのに役立ちます。 |
操作 | デバッグ | オンラインデバッグ画面に入り、モデルインターフェースをテストします。 | 標準化されたREST API呼び出しアドレスを提供します(サービスグループが実行状態である必要があります)。 |
| バージョン追加 | 同じサービスに新しいモデルバージョンをデプロイします。 | モデルのグレーリリースまたはA/Bテストのシナリオを実現し、最大2つのサービスバージョンをサポートします。 |
| 権限設定 | サービスの権限を設定します。 | 読み取り、書き込み、管理の権限を設定できます。(エンティティ権限管理モードを有効にした場合のみ有効です) |
| 削除 | モデルサービス資産およびその関連リソースを完全に削除します。 | 操作は元に戻せません。削除前に、このサービスグループが停止していることを確認してください。 |
{"client_request_id": "123456","dataframe_split": {"columns": ["fixed_acidity", "volatile_acidity", "citric_acid", "residual_sugar", "chlorides", "free_sulfur_dioxide", "total_sulfur_dioxide", "density", "pH", "sulphates", "alcohol"],"data": [[1, 0.8, 0.7, 0.5, 1, 1.5, 0.8, 0.7, 0.5, 0.8, 0.5]]}}
{"client_request_id": "123456","dataframe_split": {"columns": ["fixed_acidity", "volatile_acidity", "citric_acid", "residual_sugar", "chlorides", "free_sulfur_dioxide", "total_sulfur_dioxide", "density", "pH", "sulphates", "alcohol"],"data": [[1, 0.8, 0.7, 0.5, 1, 1.5, 0.8, 0.7, 0.5, 0.8, 0.5],[0.9, 0.7, 0.6, 0.4, 0.9, 1.2, 0.7, 0.6, 0.4, 0.7, 0.4]]}}
curl -X POST https://[サービス呼び出しアドレス]/predict \\-H 'Authorization: [認証Token]' \\-H 'Content-Type: application/json' \\-d '{"client_request_id":"123456","dataframe_split":{"columns":["fixed_acidity","volatile_acidity","citric_acid","residual_sugar","chlorides","free_sulfur_dioxide","total_sulfur_dioxide","density","pH","sulphates","alcohol"],"data":[[1,0.8,0.7,0.5,1,1.5,0.8,0.7,0.5,0.8,0.5]]}}'




フィールド分類 | 説明 | 説明 | |
ID | | サービスバージョンインスタンスの一意の識別子です。 | システムによって自動生成される一意の文字列で、異なるサービスバージョンを正確に特定し区別するために使用されます。 |
サービス名 | | 当該サービスの具体的な名前です。 | マルチバージョン管理とグレーリリースを容易に行えます。 |
サービスバージョン | 当該サービス | 当該サービスのバージョン番号です。 | マルチバージョン管理とグレーリリースを容易に行えます。 |
ステータス | | サービスバージョンの現在の実行ライフサイクル状態です。 | このバージョンの実行状態を表示します:草稿/実行中/停止済みなど。 |
サービスの説明 | | 当該サービスバージョンの用途または特性について説明します。 | チームでのコラボレーション時に各サービスバージョンの違いを理解するのに役立ちます。 |
モデルソース | | 当該サービスに関連付けられた基盤モデルアセットを公開します。 | このサービスがモデル管理モジュール内のどの具体的なモデル名を使用しているかを表示します(例:ml_wine_db_wine_model)。 |
リソースソース | | 当該バージョンの実行に消費されるコンピューティングリソースのタイプです。 | リソースが「プラットフォーム従量課金リソース」または「CVMリソースグループ」のいずれから来ているかを識別します。 |
トラフィック割り当て | | マルチバージョンが併存する場合に、当該バージョンが受け取るトラフィックの重みです。 | A/Bテストまたはグレーリリースのシナリオにおいて、当該バージョンに割り当てられたトラフィックの割合を表示します。 |
作成者 | | 当該サービスバージョンを初期化したユーザーアカウントです。 | このバージョンの作成者を記録し、権限管理と操作監査に使用します。 |
作成時間 | | 当該サービスバージョンが初めて作成された時間です。 | システムが自動的に記録するため、時間軸に沿ってモデルの反復プロセスを追跡しやすくなります。 |
更新日時 | | 当該サービスバージョンが最後に更新された時間です。 | システムが自動的に記録するため、時間軸に沿ってモデルの反復プロセスを追跡しやすくなります。 |
操作 | 更新します。 | 現在のサービスバージョンの設定情報を変更します。 | サービスバージョンの詳細を表示し、サービスバージョンの説明、リソース設定などのパラメータを更新できます。 |
| 監視 | 当該バージョンのリアルタイムパフォーマンス指標を表示します。 | QPS、呼び出し遅延、CPU/GPU使用率などの可視化監視ビューにアクセスします。 |
| ログ | 当該サービスインスタンスの実行ログを検索します。 | モデルコードのエラー、入出力異常などの実行時問題を調査するために使用します。 |
| 起動/停止 | サービスインスタンスの実行状態を手動で制御します。 | 「起動」をクリックするとサービスグループが実行状態に変更され、「停止」をクリックするとサービスリソースが解放されます。 |
| 削除 | 当該サービスバージョンを完全に削除します。 | 操作は元に戻せません。削除前に、このバージョンが停止していることを確認してください。 |

フィールド名称 | 説明 | 説明 |
サービス名 | 当該サービスの具体的なバージョン識別子です。 | マルチバージョン管理とグレーリリースを容易に行えます。 |
サービスID | サービスバージョンインスタンスの一意の識別子です。 | システムによって自動生成される一意の文字列で、異なるサービスバージョンを正確に特定し区別するために使用されます。 |
サービスの説明 | 当該サービスバージョンの用途または特性について説明します。 | チームでのコラボレーション時に各サービスバージョンの違いを理解するのに役立ちます。 |
課金モデル | リソースの課金方式 | 例えばPay-as-you-go(従量課金)は、モデル実行のコスト構造を示しています。 |
リソース仕様 | 当該バージョンに割り当てられるコンピューティングリソースのサイズです。 | 例えば4C8Gの場合、このバージョンが対応できるモデルの複雑さと同時実行数の上限を決定します。 |
接続モデルとバージョン | 関連するモデルアセットの詳細です。 | モデル管理内のモデル名と具体的なMLflowバージョン番号(例:Version2)を表示します。 |
レプリカ数 | 実行中のコンテナインスタンスの総数です。 | サービスの高可用性を決定します。複数のレプリカはトラフィックを分散し、災害復旧保護を提供できます。 |
リクエスト制限 | トラフィック保護のしきい値です。 | $QPS$の上限を表示します。しきい値に達した場合、システムはパケット破棄またはキューイング保護をトリガーします。 |
認証生成 | サービスセキュリティ制御スイッチです。 | 署名認証(API Key)が有効かどうかを表示します。無効の場合、アドレスに直接アクセスできます。 |
フィールド/操作 | 説明 | 運用保守ガイド |
インスタンス名称 | 基盤となるコンピューティングユニット(Pod)の識別子。 | 実行中のマイクロサービスノードを一意に識別します。 |
インスタンスの状態 | インスタンスの物理的な状態。 | Waitingはイメージのプル中またはスケジュール待ちを示します。Runningはサービスが準備完了であることを示します。 |
再起動回数 | コンテナが異常終了する頻度。 | コアとなる障害切り分け指標です。回数が継続的に増加する場合、モデルにメモリリークまたはコードエラーが存在する可能性を示します。 |
監視 | インスタンスレベルの監視入口です。 | 単一インスタンスの$CPU/MEM$消費量を確認し、リソースの偏りが存在するかどうかを判断します。 |
ログ | コンテナの標準出力ストリーム。 | モデル読み込みロジック、予測エラースタックを確認するための最も直接的な手段です。 |
再起動 | インスタンスを強制的に再起動します。 | インスタンスがハングしたり応答が極端に遅くなった場合に、サービスを迅速に復旧させるための緊急手段です。 |
コンテナにアクセス | 対話型ターミナル。 | コンテナ内部に入ってコマンドを実行し、ファイルパス、権限、または環境依存関係を確認することを許可します。 |

指標分類 | 主要指標項目 | ビジネス価値の説明 |
トラフィック情報 | ネットワークトラフィック、QPS、QPS制限回数、同時リクエスト数 | API呼び出しの負荷を評価します。同時リクエスト数とレート制限回数は、レプリカ数を増やす必要があるかどうかを判断するための重要なシグナルです。 |
リソース情報 | CPU使用率、MEM使用率、ビデオメモリ使用率、GPU使用率 | 基盤となるハードウェアの負荷を監視します。これにはビデオメモリ使用率とGPU使用率が含まれます。 |
インスタンス情報 | インスタンス総数、実行中のインスタンス数 | サービスの可用性を直感的に表示し、実際に稼働しているコンテナ数が設定の期待値と一致しているかどうかを確認します。 |





"""このサンプルは、Spark Streamingを使用してCOSストレージ内の推論テーブルをストリーミング読み取りし、主要フィールド(特徴、予測値)を加工処理した後、DLC内部テーブルに書き込む処理プロセスを示しています。"""## 前提条件1. このDLCエンジンに関連付けられたCOSアクセス認証情報に、推論テーブルストレージバケットへのアクセス権限があることを確認してください。2. モデルサービスが推論テーブル監視を有効にしていることを確認してください。## 実行方法チュートリアルのパラメータを変更した後、オフライン開発->オーケストレーションスペースでDLC PySparkタスクを選択して実行します。## 定時スケジュール対応するパラメータを変更してデバッグを完了した後、このタスクを定時実行に設定し、推論テーブルデータを継続的に加工できます。また、加工後の推論テーブルデータをTagデータと関連付け、Tagデータを含む推論テーブルを生成し、データ品質モジュールで推論テーブルに機械学習関連の監視指標を設定して、モデル品質を継続的に監視できます。"""from pyspark.sql import DataFrame, SparkSessionfrom pyspark.sql import functions as Ffrom pyspark.sql import types as Tfrom typing import Union, List, Dict, Optional, Sequence, Anyfrom pyspark.sql.streaming import StreamingQueryfrom pyspark.sql.types import (StructType, StructField, StringType, LongType, DoubleType,ArrayType, TimestampType)"""### 元の推論テーブルデータ形式の定義元の推論テーブルデータは特定の構造に従ってJSON形式でユーザー指定のCOSバケットに保存されます。request_schemaはユーザー入力リクエスト構造を表し、response_schemaはモデル出力構造を表します。モデルサービスに対応する実際の入出力形式に応じて調整してください。その他のフィールドは推論テーブルの固定構造であるため、通常は調整不要です。"""request_schema = StructType([StructField("client_request_id", StringType(), True),StructField("dataframe_split", StructType([StructField("columns", ArrayType(StringType()), True),StructField("data", ArrayType(ArrayType(DoubleType())), True),]), True),])request_metadata_schema = StructType([StructField("model_name", StringType(), True),StructField("model_version", StringType(), True),StructField("service_id", StringType(), True),])response_schema = StructType([StructField("predictions", ArrayType(LongType()), True),])schema = StructType([StructField("client_request_id", StringType(), True),StructField("execution_duration_ms", LongType(), True),StructField("request", request_schema, True),StructField("request_date", StringType(), True),StructField("request_metadata", request_metadata_schema, True),StructField("request_time", TimestampType(), True),StructField("requester", StringType(), True),StructField("response", response_schema, True),StructField("sampling_fraction", DoubleType(), True),StructField("status_code", LongType(), True),StructField("wedata_request_id", StringType(), True),])# データソースパラメータSOURCE_PATH = "cosn://ストレージバケットパス/" # 推論テーブルストレージパスCHECKPOINT_PATH = "cosn://ストレージバケットパス/checkpoint" # check_pointストレージパス、推論テーブルストレージパスと一致させることを推奨します# 結果テーブルパラメータUNPACKED_TABLE_NAME = "DataLakeCatalog.test.unpacked_test_inference_table" # 結果テーブル名。DLC内部テーブルの3セグメント形式のテーブル名である必要があります:<データカタログ>.<データベース>.<データテーブル>MODEL_ID_COL = "model_id" # 結果テーブルモデルID列、モデルの識別に使用しますEXAMPLE_ID_COL = "example_id" # 結果テーブルレコードの一意のID列、ユーザー更新操作PREDICTION_COL = "prediction" # 予測値列名FEATURE_COLUMNS = ["sepal_length", "sepal_width", "petal_length", "petal_width"] # 特徴列名。モデルの特徴に応じて調整しますdef process_requests(requests_raw: DataFrame) -> DataFrame:"""リクエスト特徴を個別の列に展開し、対応する予測結果とペアリングします。Args:requests_raw: 処理対象データReturn:処理済みデータ"""# 成功したリクエストをフィルタリングしますrequests_success = requests_raw.filter(F.col("status_code") == 200).drop("status_code")# モデル識別子を生成しますrequests_identified = requests_success \\.withColumn(MODEL_ID_COL, F.concat(F.col("request_metadata").getItem("model_name"), F.lit("_"), F.col("request_metadata").getItem("model_version"))) \\.drop("request_metadata")# 特徴列と予測結果を展開します# 1. 特徴列名、特徴データ、予測値を取得しますrequests_with_features = (requests_identified.withColumn("feature_columns", F.col("request.dataframe_split.columns")).withColumn("feature_data", F.col("request.dataframe_split.data")).withColumn("predictions", F.col("response.predictions")))# 2. 各データ行を対応する予測結果とペアリングします。requests_exploded = (requests_with_features.withColumn("feature_prediction_pairs",F.arrays_zip(F.col("feature_data"), F.col("predictions"))).withColumn("feature_prediction_pairs",F.explode(F.col("feature_prediction_pairs"))).withColumn("feature_row", F.col("feature_prediction_pairs.feature_data")).withColumn(PREDICTION_COL, F.col("feature_prediction_pairs.predictions")))# 3. 特徴列を動的に作成しますrequests_with_feature_cols = requests_explodedfor i, col_name in enumerate(FEATURE_COLUMNS):requests_with_feature_cols = (requests_with_feature_cols.withColumn(col_name, F.col("feature_row")[i]))# 4. レコードの一意のIDを追加し、後続のupsert操作を容易にします。requests_with_example_id = requests_with_feature_cols \\.withColumn(EXAMPLE_ID_COL, F.expr("uuid()"))# 5. 一時列をクリーンアップします。requests_processed = (requests_with_example_id.drop("feature_columns", "feature_data", "feature_prediction_pairs", "feature_row", "predictions", "request", "response"))return requests_processeddef create_table(spark: SparkSession,table_name: str,df: Optional[DataFrame] = None,partition_expr: str = None,description: Optional[str] = None,):"""dlc内部テーブルを作成します。Args:spark:SparkSessionインスタンスtable_name: テーブル完全名(形式:データカタログ.データベース.データテーブル)df: 初期データ(スキーマ推論に使用)partition_expr: パーティション列(ストレージクエリを最適化)description: テーブル説明Raises:ValueError:異常作成時にスローされます。"""# テーブルスキーマを推論します。table_schema = df.schema# 列定義を構築します。columns_ddl = []for field in table_schema.fields:data_type = field.dataType.simpleString().upper()col_def = f"`{field.name}` {data_type}"if not field.nullable:col_def += " NOT NULL"columns_ddl.append(col_def)# 建表文を構築します。ddl = f"""CREATE TABLE IF NOT EXISTS {table_name} ({', '.join(columns_ddl)})USING icebergPARTITIONED BY ({partition_expr})TBLPROPERTIES ('comment'= '{description or ''}','format-version'= '2','write.metadata.previous-versions-max'= '100','write.metadata.delete-after-commit.enabled'= 'true','smart-optimizer.inherit' = 'none','smart-optimizer.written.enable' = 'enable')"""# sqlを出力します。print(f"create table ddl: {ddl}\\n")# DDLを実行します。try:spark.sql(ddl)except Exception as e:raise ValueError(f"Failed to create table: {str(e)}") from eprint(f"create table {table_name} done")spark = SparkSession.builder.appName("Operate DB Example").getOrCreate()# ストリーミングDataFrameを構築します。df = (spark.readStream.format("json").schema(schema).load(SOURCE_PATH))# ストリーミングデータを処理します。unpacked_df = process_requests(df)# 結果テーブルを作成し、request_timeをパーティションフィールドとして、日ごとにパーティションを作成します。モデルサービスのリクエスト量に応じて調整できます。create_table(spark, UNPACKED_TABLE_NAME, unpacked_df, 'days(request_time)')# データを書き込みます。query = unpacked_df.writeStream \\.format("parquet") \\.outputMode("append") \\.option("checkpointLocation", CHECKPOINT_PATH) \\.trigger(once=True) \\.toTable(UNPACKED_TABLE_NAME)query.awaitTermination()spark.sql(f"select * from {UNPACKED_TABLE_NAME}").show(10)
"""このサンプルは、Spark Streamingを使用してCOSストレージ内の推論テーブルをストリーミング読み取りし、主要フィールド(特徴、予測値)を加工処理した後、EMR Hiveテーブルに書き込む処理プロセスを示しています。## 前提条件1. このDLCエンジンに関連付けられたCOSアクセス認証情報に、推論テーブルストレージバケットへのアクセス権限があることを確認してください。2. モデルサービスが推論テーブル監視を有効にしていることを確認してください。## 実行方法チュートリアルのパラメータを変更した後、オフライン開発->オーケストレーションスペースでEMR PySparkタスクを選択して実行します。## 定時スケジュール対応するパラメータを変更してデバッグを完了した後、このタスクを定時実行に設定し、推論テーブルデータを継続的に加工できます。また、加工後の推論テーブルデータをTagデータと関連付け、Tagデータを含む推論テーブルを生成し、データ品質モジュールで推論テーブルに機械学習関連の監視指標を設定して、モデル品質を継続的に監視できます。"""from pyspark.sql import DataFrame, SparkSessionfrom pyspark.sql import functions as Ffrom pyspark.sql import types as Tfrom typing import Union, List, Dict, Optional, Sequence, Anyfrom pyspark.sql.streaming import StreamingQueryfrom pyspark.sql.types import (StructType, StructField, StringType, LongType, DoubleType,ArrayType, TimestampType)"""### 元の推論テーブルデータ形式の定義元の推論テーブルデータは特定の構造に従ってJSON形式でユーザー指定のCOSバケットに保存されます。request_schemaはユーザー入力リクエスト構造を表し、response_schemaはモデル出力構造を表します。モデルサービスに対応する実際の入出力形式に応じて調整してください。その他のフィールドは推論テーブルの固定構造であるため、通常は調整不要です。"""request_schema = StructType([StructField("client_request_id", StringType(), True),StructField("dataframe_split", StructType([StructField("columns", ArrayType(StringType()), True),StructField("data", ArrayType(ArrayType(DoubleType())), True),]), True),])request_metadata_schema = StructType([StructField("model_name", StringType(), True),StructField("model_version", StringType(), True),StructField("service_id", StringType(), True),])response_schema = StructType([StructField("predictions", ArrayType(LongType()), True),])schema = StructType([StructField("client_request_id", StringType(), True),StructField("execution_duration_ms", LongType(), True),StructField("request", request_schema, True),StructField("request_date", StringType(), True),StructField("request_metadata", request_metadata_schema, True),StructField("request_time", TimestampType(), True),StructField("requester", StringType(), True),StructField("response", response_schema, True),StructField("sampling_fraction", DoubleType(), True),StructField("status_code", LongType(), True),StructField("wedata_request_id", StringType(), True),])# データソースパラメータSOURCE_PATH = "cosn://ストレージバケットパス/" # 推論テーブルストレージパスCHECKPOINT_PATH = "cosn://ストレージバケットパス/checkpoint" # check_pointストレージパス、推論テーブルストレージパスと一致させることを推奨します# 結果テーブルパラメータUNPACKED_TABLE_NAME = "testdb.unpacked_test_inference_table" # 結果テーブル名。hiveテーブル名である必要があります:<データベース>.<データテーブル>MODEL_ID_COL = "model_id" # 結果テーブルモデルID列、モデルの識別に使用しますEXAMPLE_ID_COL = "example_id" # 結果テーブルレコードの一意のID列、ユーザー更新操作PREDICTION_COL = "prediction" # 予測値列名FEATURE_COLUMNS = ["sepal_length", "sepal_width", "petal_length", "petal_width"] # 特徴列名。モデルの特徴に応じて調整しますdef process_requests(requests_raw: DataFrame) -> DataFrame:"""リクエスト特徴を個別の列に展開し、対応する予測結果とペアリングします。Args:requests_raw: 処理対象データReturn:処理済みデータ"""# 成功したリクエストをフィルタリングしますrequests_success = requests_raw.filter(F.col("status_code") == 200).drop("status_code")# モデル識別子を生成しますrequests_identified = requests_success \\.withColumn(MODEL_ID_COL, F.concat(F.col("request_metadata").getItem("model_name"), F.lit("_"), F.col("request_metadata").getItem("model_version"))) \\.drop("request_metadata")# 特徴列と予測結果を展開します# 1. 特徴列名、特徴データ、予測値を取得しますrequests_with_features = (requests_identified.withColumn("feature_columns", F.col("request.dataframe_split.columns")).withColumn("feature_data", F.col("request.dataframe_split.data")).withColumn("predictions", F.col("response.predictions")))# 2. 各データ行を対応する予測結果とペアリングします。requests_exploded = (requests_with_features.withColumn("feature_prediction_pairs",F.arrays_zip(F.col("feature_data"), F.col("predictions"))).withColumn("feature_prediction_pairs",F.explode(F.col("feature_prediction_pairs"))).withColumn("feature_row", F.col("feature_prediction_pairs.feature_data")).withColumn(PREDICTION_COL, F.col("feature_prediction_pairs.predictions")))# 3. 特徴列を動的に作成しますrequests_with_feature_cols = requests_explodedfor i, col_name in enumerate(FEATURE_COLUMNS):requests_with_feature_cols = (requests_with_feature_cols.withColumn(col_name, F.col("feature_row")[i]))# 4. レコードの一意のIDを追加し、後続のupsert操作を容易にします。requests_with_example_id = requests_with_feature_cols \\.withColumn(EXAMPLE_ID_COL, F.expr("uuid()"))# 5. 一時列をクリーンアップします。requests_processed = (requests_with_example_id.drop("feature_columns", "feature_data", "feature_prediction_pairs", "feature_row", "predictions", "request", "response"))return requests_processeddef create_table(spark: SparkSession,table_name: str,df: Optional[DataFrame] = None,partition_expr: str = None,description: Optional[str] = None,):"""hiveテーブルを作成します。Args:spark:SparkSessionインスタンスtable_name: hiveテーブル完全名(形式:データベース.データテーブル)df: 初期データ(オプション、スキーマ推論に使用)partition_expr: パーティション列(ストレージクエリの最適化)description: テーブル説明Raises:ValueError:異常作成時にスローされます。"""# テーブルスキーマを推論します。table_schema = df.schemapart_col_nam = partition_expr.split(' ')[0]# 列定義を構築します。columns_ddl = []for field in table_schema.fields:# テーブル作成時にパーティション列を除外します。if field.name == part_col_nam:continuedata_type = field.dataType.simpleString().upper()col_def = f"`{field.name}` {data_type}"if not field.nullable:col_def += " NOT NULL"columns_ddl.append(col_def)# 建表文を構築します。ddl = f"""CREATE TABLE IF NOT EXISTS {table_name} ({', '.join(columns_ddl)})PARTITIONED BY ({partition_expr})TBLPROPERTIES ('comment'= '{description or ''}')"""# sqlを出力します。print(f"create table ddl: {ddl}\\n")# DDLを実行します。try:spark.sql(ddl)except Exception as e:raise ValueError(f"Failed to create table: {str(e)}") from eprint(f"create table {table_name} done")def write_batch_to_hive(batch_df: DataFrame, batch_id: int, table_name: str):# 小ファイルの制御:パーティション列による再パーティションout_df = batch_df.repartition(8, "dt")out_df.write.mode("append").format("hive").saveAsTable(table_name,partitionBy="dt")spark = SparkSession.builder.appName("Operate DB Example").enableHiveSupport().getOrCreate()# ストリーミングDataFrameを構築します。df = (spark.readStream.format("json").schema(schema).load(SOURCE_PATH))# ストリーミングデータを処理します。unpacked_df = process_requests(df)# パーティション列を挿入します。requests_with_dt = (unpacked_df.withColumn("dt", F.substring(F.col("request_date"), 1, 10)) # YYYY-MM-DD形式の日付を抽出します。)# 結果テーブルを作成します。create_table(spark, UNPACKED_TABLE_NAME, unpacked_df, 'dt STRING')# Hive動的パーティションを設定します。spark.sql("SET hive.exec.dynamic.partition=true")spark.sql("SET hive.exec.dynamic.partition.mode=nonstrict")# 結果テーブルにバッチで書き込みます。query = (requests_with_dt.writeStream.outputMode("append").option("checkpointLocation", CHECKPOINT_PATH).trigger(once=True).foreachBatch(lambda df, id: write_batch_to_hive(df, id, UNPACKED_TABLE_NAME)).start())query.awaitTermination()# 結果データを照会します。spark.sql(f"select * from {UNPACKED_TABLE_NAME}").show(10)

from pyspark.sql import DataFrame, SparkSessionfrom typing import Union, List, Dict, Optional, Sequence, Any# タグを関連付ける推論テーブル名:DLC内部テーブルの3セグメント形式のテーブル名である必要があります:<データカタログ>.<データベース>.<データテーブル>UNPACKED_TABLE_NAME = "DataLakeCatalog.test.unpacked_test_inference_table"# タグデータテーブル設定:複数指定できます。各テーブルには構造(<テーブル名>、<joinで保持するフィールド名リスト>、<join時に等値条件で結合するフィールドリスト>)が含まれている必要があります。JOIN_TABLES = [('DataLakeCatalog.test.test_label_table', ['label', 'example_id'], ['example_id'])]# タグデータ関連付け後の推論テーブル名FULLY_QUALIFIED_TABLE_NAME = "DataLakeCatalog.test.test_fully_qualified_table_name"# ウィンドウサイズ: このNotebookスクリプトを実行するたびに処理するデータの最大期間を制限します。このウィンドウより前のデータで未処理のものは無視されます。すべてのデータが処理されるように、スケジュール周期はこのウィンドウサイズより小さくする必要があります。PROCESSING_WINDOW_DAYS = 10# 結果テーブル挿入時の主キーフィールドMERGE_COLS = ["request_time", "example_id"]def create_table(spark: SparkSession,table_name: str,df: Optional[DataFrame] = None,partition_expr: str = None,description: Optional[str] = None,):"""dlc内部テーブルを作成します。Args:spark: SparkSessionインスタンスtable_name: テーブル完全名(形式:データカタログ.データベース.データテーブル)df: 初期データ(スキーマ推論に使用)partition_expr: パーティション列(ストレージクエリの最適化)description: テーブル説明Raises:ValueError: 異常作成時にスローされます"""# テーブルスキーマを推論しますtable_schema = df.schema# 列定義を構築しますcolumns_ddl = []for field in table_schema.fields:data_type = field.dataType.simpleString().upper()col_def = f"`{field.name}` {data_type}"if not field.nullable:col_def += " NOT NULL"columns_ddl.append(col_def)# 建表文を構築しますddl = f"""CREATE TABLE IF NOT EXISTS {table_name} ({', '.join(columns_ddl)})USING icebergPARTITIONED BY ({partition_expr})TBLPROPERTIES ('comment'= '{description or ''}','format-version'= '2','write.metadata.previous-versions-max'= '100','write.metadata.delete-after-commit.enabled'= 'true','smart-optimizer.inherit' = 'none','smart-optimizer.written.enable' = 'enable')"""# sqlを出力しますprint(f"create table ddl: {ddl}\\n")# DDLを実行しますtry:spark.sql(ddl)except Exception as e:raise ValueError(f"Failed to create table: {str(e)}") from eprint(f"create table {table_name} done")def upsert_table(spark: SparkSession,target_table_name: str,merge_cols: list,df: DataFrame,):"""upsert方式でターゲットテーブルにデータを書き込みます。Args:spark: SparkSession インスタンスtarget_table_name: 結果テーブル完全名(形式:データカタログ.データベース.データテーブル)merge_cols: 更新時の主キーdf: 更新対象データRaises:ValueError:書き込み異常時にスローされます。"""merge_condition = " AND ".join([f"target.{col} = source.{col}" for col in merge_cols])# 一時ビューを作成します。df.createOrReplaceTempView("source_data")# MERGE操作を実行します。merge_sql = f"""MERGE INTO {target_table_name} AS targetUSING source_data AS sourceON {merge_condition}WHEN MATCHED THEN UPDATE SET *WHEN NOT MATCHED THEN INSERT *"""# DMLを実行します。try:spark.sql(merge_sql)except Exception as e:raise ValueError(f"Failed to create table: {str(e)}") from eprint(f"upsert table {target_table_name} done")spark = SparkSession.builder.appName("Operate DB Example").getOrCreate()# 毎回PROCESSING_WINDOW_DAYSのデータを読み取ります。requests_processed = spark.table(UNPACKED_TABLE_NAME) \\.filter(f"CAST(request_time AS DATE) >= current_date() - (INTERVAL {PROCESSING_WINDOW_DAYS} DAYS)")if requests_processed.count() > 0:# タグテーブルを関連付けます。for table_name, preserve_cols, join_cols in JOIN_TABLES:join_data = spark.table(table_name)requests_processed = requests_processed.join(join_data.select(preserve_cols), on=join_cols, how="left")# 結果テーブルを作成します。create_table(spark, FULLY_QUALIFIED_TABLE_NAME, requests_processed, 'days(request_time)')# 結果テーブルに書き込みます。upsert_table(spark, FULLY_QUALIFIED_TABLE_NAME, MERGE_COLS, requests_processed)spark.sql(f"select * from {FULLY_QUALIFIED_TABLE_NAME}").show(10)
from pyspark.sql import DataFrame, SparkSessionfrom typing import Union, List, Dict, Optional, Sequence, Any# タグを関連付ける推論テーブル名:Hiveテーブル名である必要があります:<データベース>.<データテーブル>UNPACKED_TABLE_NAME = "testdb.unpacked_test_inference_table"# タグデータテーブル設定:複数指定できます。各テーブルには構造(<テーブル名>、<joinで保持するフィールド名リスト>、<join時に等値条件で結合するフィールドリスト>)が含まれている必要があります。JOIN_TABLES = [('testdb.test_label_table', ['label', 'example_id'], ['example_id'])]# タグデータ関連付け後の推論テーブル名FULLY_QUALIFIED_TABLE_NAME = "testdb.test_fully_qualified_table_name"# ウィンドウサイズ: このNotebookスクリプトを実行するたびに処理するデータの最大期間を制限します。このウィンドウより前のデータで未処理のものは無視されます。すべてのデータが処理されるように、スケジュール周期はこのウィンドウサイズより小さくする必要があります。PROCESSING_WINDOW_DAYS = 10def create_table(spark: SparkSession,table_name: str,df: Optional[DataFrame] = None,partition_expr: str = None,description: Optional[str] = None,):"""hiveテーブルを作成します。Args:spark: SparkSessionインスタンスtable_name: hiveテーブル完全名(形式:データベース.データテーブル)df: 初期データ(オプション、スキーマ推論に使用)partition_expr: パーティション列(ストレージクエリの最適化)description: テーブルの説明Raises:ValueError: 作成異常時にスローされます。"""# テーブルスキーマを推論します。table_schema = df.schemapart_col_nam = partition_expr.split(' ')[0]# 列定義を構築します。columns_ddl = []for field in table_schema.fields:# テーブル作成時にパーティション列を除外します。if field.name == part_col_nam:continuedata_type = field.dataType.simpleString().upper()col_def = f"`{field.name}` {data_type}"if not field.nullable:col_def += " NOT NULL"columns_ddl.append(col_def)# テーブル作成文を構築します。ddl = f"""CREATE TABLE IF NOT EXISTS {table_name} ({', '.join(columns_ddl)})PARTITIONED BY ({partition_expr})TBLPROPERTIES ('comment'= '{description or ''}')"""# sqlを出力します。print(f"create table ddl: {ddl}\\n")# DDLを実行します。try:spark.sql(ddl)except Exception as e:raise ValueError(f"Failed to create table: {str(e)}") from eprint(f"create table {table_name} done")def partition_overwrite(spark, source_df, target_table):""""""try:# データが空かどうかを確認します。if source_df.count() == 0:print(f"警告: {target_table}に書き込むデータがありません。")return# 上書きするパーティションを表示します。partitions = source_df.select("dt").distinct().collect()partition_list = [row.dt for row in partitions]print(f"上書きするパーティション: {partition_list}")# パラメータを設定して書き込みます。spark.sql("SET hive.exec.dynamic.partition=true")spark.sql("SET hive.exec.dynamic.partition.mode=nonstrict")spark.conf.set("spark.sql.sources.partitionOverwriteMode", "dynamic")source_df.repartition(8, "dt") \\.write \\.mode("overwrite") \\.format("hive") \\.saveAsTable(target_table)print(f"{len(partition_list)} 個のパーティションをテーブル {target_table} に正常に上書きしました。")except Exception as e:print(f"テーブル {target_table} への書き込み中にエラーが発生しました: {str(e)}")raisespark = SparkSession.builder.appName("Operate DB Example").getOrCreate()# 毎回PROCESSING_WINDOW_DAYS分区のデータを読み取り、処理後に上書き書き込みを行います。requests_processed = spark.table(UNPACKED_TABLE_NAME) \\.filter(f"dt >= date_format(current_date() - INTERVAL {PROCESSING_WINDOW_DAYS} DAYS, 'yyyy-MM-dd')")for table_name, preserve_cols, join_cols in JOIN_TABLES:join_data = spark.table(table_name)requests_processed = requests_processed.join(join_data.select(preserve_cols), on=join_cols, how="left")create_table(spark, FULLY_QUALIFIED_TABLE_NAME, requests_processed, 'dt STRING')partition_overwrite(spark, requests_processed, FULLY_QUALIFIED_TABLE_NAME)spark.sql(f"select * from {FULLY_QUALIFIED_TABLE_NAME}").show(10)










フィードバック