Amazon Web Services ブログ

AWS Glue と SAP データで RISE 拡張

多くのお客様がSAP のソースデータと SAP 以外のソースデータを組み合わせて活用したいと考えています。このようなデータ分析のユースケースは、データウェアハウスやデータレイクを構築することで実現できます。お客様は AWS Glue の SAP OData コネクタを使用して、SAP からデータを抽出できます。SAP OData コネクタは、オンプレミス又はクラウド (ネイティブと SAP RISE) で稼働しているシステムの両方をサポートしています。AWS Glue の SAP OData コネクタを使用すると、AWS Glue と Apache Spark で効率的な処理のためにデータをシームレスに分散処理できます。AWS Glue は、サーバーレスのデータ統合サービスで、分析、機械学習 (ML)、アプリケーション開発などに対し、複数のソースからデータを検索、準備、移動、結合することが簡単になります。

AWS Glue の SAP OData コネクタは、データ抽出のために SAP ODP フレームワークと OData プロトコルを使用します。このフレームワークは、プロバイダ・サブスクライバモデルで動作し、SAP システムと SAP 以外のターゲット間のデータ転送を実現しています。ODP フレームワークは、Operational Delta Queues (ODQ) メカニズムを通じて、フルデータ抽出と差分データキャプチャをサポートしています。SAP のデータ抽出のソースとして、SAP データエクストラクタ、ABAP CDS ビュー、SAP BW・BW/4 HANA ソース、SAP ABAP ソースの HANA Information ビュー、または ODP 対応の他のデータソースを使用できます。

SAP のソースシステムには履歴データが保持されており、常に更新があります。このため、ソースの変更を増分処理できるようにすることが必要です。このブログでは、SAP からデータを抽出し、SAP ODP フレームワークとデルタトークンを使用して SAP ソースからの増分データ抽出を実現する方法を説明します。

ソリューションの概要

SAP ソース システムに保存されている製品データを分析したいと考えている例になります。お客様は、現在提供している製品ラインナップ、特に各品目グループに含まれる製品の数を把握したいと考えています。それには、SAP 品目マスターと SAP システムの品目グループ データ ソースからのデータを結合する必要があります。SAP 品目マスター データは増分抽出で使用できますが、SAP 品目グループはフル ロードでのみ使用できます。これらのデータ ソースを結合し、分析のためにクエリできるようにする必要があります。

前提条件

このブログで紹介したソリューションを実装するには、まず次の前提条件のステップを実施してください。

  1. SAP システムの SAP Gateway で、ODP データソースを使って SAP OData サービスを設定します。
  2. SAP データを保存するための Amazon Simple Storage Service (Amazon S3) バケットを作成します。
  3. AWS Glue Data Catalog で、sapgluedatabase という名前のデータベースを作成します。
  4. AWS Glue の抽出、変換、ロード (ETL) ジョブで使用する AWS Identity and Access Management (IAM) ロールを作成します。このロールには、Amazon S3 と AWS Secrets Manager を含むすべての必要なリソースへのアクセス権限を付与する必要があります。このブログのソリューションでは、このロールを GlueServiceRoleforSAP と名付けます。以下のポリシーを使用します。
    • AWS 管理ポリシー:
    • インラインポリシー:
      {
             "Version": "2012-10-17",
             "Statement": [ 
                    {
                            "Sid": "VisualEditor0",
                            "Effect": "Allow",
                            "Action": [ 
                                   "s3:PutObject",
                                   "s3:GetObjectAcl",
                                   "s3:GetObject",
                                   "s3:GetObjectAttributes",
                                   "s3:ListBucket",
                                   "s3:DeleteObject",
                                   "s3:PutObjectAcl"],
                            "Resource": [ 
                                   "arn:aws:s3:::<S3-BUCKET-NAME>",
                                   "arn:aws:s3:::<S3-BUCKET-NAME>/*"
                            ] 
                    }
             ] 
      }
      
      Code

SAP 用の AWS Glue 接続先の作成

SAP コネクタは、CUSTOM ( SAP BASIC 認証) と OAUTH の両方の認証方式をサポートしています。この例では、BASIC 認証で接続します。

  1. AWS マネジメントコンソール で AWS Secrets Manager サービスを開いて、ODataGlueSecret という名前のシークレットを作成します。AWS Secrets Manager の詳細には、次のコードを含める必要があります。<your SAP username> の部分にあなたの SAP システムのユーザー名を、<your SAP username password> の部分にそのパスワードを入力します。
    {
       "basicAuthUsername": "<your SAP username>",
       "basicAuthPassword": "<your SAP username password>",
       "basicAuthDisableSSO": "True",
       "customAuthenticationType": "CustomBasicAuth"
    }
    
    Code

  2. SAP OData データソースを選択して、AWS Glue で SAP への接続先 GlueSAPOdata を作成します。
  3. SAP ソースの適切な値を使用して接続を構成します。
    1. アプリケーションホスト URL: ホストには、SAP ホスト名を認証するための SSL 証明書が必要
    2. アプリケーションサービスパス: /sap/opu/odata/iwfnd/catalogservice;v=2;
    3. ポート番号: SAP ソースシステムのポート番号
    4. クライアント番号: SAP ソースシステムのクライアント番号
    5. ログオン言語: SAP ソースシステムのログオン言語
  4. 認証セクションで、認証タイプCUSTOM を選択します。
  5. 前の手順で作成したシークレット SAPODataSecret を選択します。
  6. ネットワークオプションセクションで、SAP システムへ接続するための VPCサブネットセキュリティグループを入力します。SAP システムへの接続の詳細については、ETL ジョブ用の VPC を構成するを参照してください。

SAP からデータを取り込むための ETL ジョブの作成

AWS Glue コンソールで、新しいビジュアルエディターでジョブを作成します。

  1. AWS Glue コンソールにアクセスします。
  2. ナビゲーションペインの ETL ジョブの下にある Visual ETL を選択します。
  3. Visual ETL を選択して、ビジュアルエディターでジョブを作成します。
  4. ジョブ名をデフォルトの名称から Material Master Job に編集し、保存を選択します。

ビジュアルエディターキャンバス上で、SAP ソースを選択します。

  1. Visual タブを選択し、プラス記号をクリックして Add nodes メニューを開きます。SAP を検索し、SAP OData Source を追加します。
  2. 追加したノードの名前を Material Master Attributes に設定します。
    1. SAP OData connection では、GlueSAPOData 接続先を選択します。
    2. SAP ソースから製品マスタ、サービス、エンティティセットを選択します。
    3. Entity NameSub Entity Name では、SAP ソースの SAP OData エンティティを選択します。
    4. Fields から、Material、Created on、Material Group、Material Type、Old Matl number、GLUE_FETCH_SQ、DELTA_TOKEN、DML_STATUS を選択します。
    5. フィルターに limit 100 と入力し、プレビューの表示にかかる時間を制限します。

この OData サービスは差分抽出をサポートしているため、増分転送オプションがデフォルトで選択されています。

AWS Glue サービスロールの詳細を選択した後、データプレビューが使用可能になります。プレビューで表示されるように、次の 3 つの新しいフィールドを含めることができます。各フィールドの意味は下記の通りです。

  • glue_fetch_sq: これはシーケンスフィールドで、レコードが受信された順序の EPOC タイムスタンプから生成され、各レコードで持つユニークの値です。ソースシステムの変更順序を確認する必要がある場合に使用できます。
  • delta_token: 最後に抽出されたレコードのみに値が含まれ、それ以外のすべてのレコードには空白になります。これは変更されたレコード (CDC) をキャプチャするための ODQ トークン値です。このレコードはソースからのトランザクションデータレコードではなく、デルタトークン値を渡す目的だけで存在します。
  • dml_status: これは、ソースから新規挿入および更新されたレコードに対して UPDATED、ソースから削除されたレコードに対して DELETED と表示されます。

デルタ対応の抽出では、最後に抽出されたレコードに DELTA_TOKEN の値が含まれ、上記のように delta_token フィールドが埋められます。

  1. ビジュアルキャンバスに別の SAP ODATA ソース接続を追加し、このノードを Material Group Text と名付けてください。
    1. SAP ソースから製品グループの OData サービスとエンティティセットを選択します
    2. Entity Name Sub Entity Name については、SAP ソースの SAP OData エンティティを選択します

この サービスはフル抽出のみをサポートしているため、完全転送オプションがデフォルトで選択されています。また、このデータセットをプレビュー表示することもできます。

  1. データをプレビューで表示するときは、language key に注目してください。フィルタがなければ SAP はすべての言語を渡すようになるため、SPRAS = 'E' というフィルターを追加して、英語のみを抽出します。ここのフィルタ―の値はフィールドの SAP 内部書式の値を使います。
  2. Material Group Text の後に、キャンバスに Change Schema 変換ノードを追加します。
    • target key で、製品グループフィールドの名前を matkl2 に変更します。これにより、最初のソースとは異なる名前になります。
    • Drop チェックボックスで、sprasodq_changemodeodq_entitycntrdml_status、delta_tokenglue_fetch_sq を選択します。

  3. キャンバスに Join 変換ノードを追加し、両方のソースデータセットを結合します。
    1. Node parents で Material Master AttributesChange Schema 両方が選択します。
    2. Join type として Left join を選択します。
    3. 各ソースのキーフィールドを Join conditions として設定します。
      • Material Master Attributes ではmatkl を選択します
      • Change Schema ではmatkl2 を選択します

出力をプレビューして、正しくデータが読み込まれていることを確認できます。これで結果を保存する準備ができました。

  1. キャンバスにターゲットの S3 バケットを追加します。
    1. ノードの親が Join に指定します。
    2. フォーマットでは、Parquet を選択します。
    3. S3 ターゲットロケーションでは、前提条件の章で作成した S3 バケットを参照し、materialmaster/S3 ターゲットロケーションに追加します。
    4. データカタログ更新オプションでは、Create a table in the Data Catalog and on subsequent runs, update the schema and add new partitionsを選択します。
    5. データベースでは、前に作成した AWS Glue データベース sapgluedatabase の名前を選択します。
    6. テーブル名には materialmaster と入力します。
  2. 保存ボタンをクリックしてジョブを保存します。ジョブは次の図のようになります。

ETL ジョブのクローンして差分対応実施

ETL ジョブを作成したら、デルタトークンを使用してインクリメンタルデータ処理を含めるためのクローンの準備が整います。

これを行うには、ジョブスクリプトを直接修正する必要があります。スクリプトを修正して、最後のデルタトークン (ジョブタグに格納される) を取得するステートメントを追加し、デルタトークン値をリクエスト (またはジョブの実行) に追加します。これにより、次回のジョブ実行時にデータを取得する際に、デルタ対応の SAP OData サービスが有効になります。

最初のジョブの実行では、タグにデルタトークン値がないため、呼び出しは初回実行となり、その後デルタトークンがタグに格納されて、将来の実行に使用されます。

    1. AWS Glue コンソールに移動します。
    2. ナビゲーションペインの ETL Jobs の下にある Visual ETL を選択します。
    3. Material Master Job を選択し、Actions を選んで Clone job を選択します。
    4. ジョブの名前を Material Master Job Delta に変更し、Script タブを選択します。
    5. 各ジョブ実行時のデルタトークンの保存と取得を行うための追加の Python ライブラリを追加する必要があります。これを行うには、Job Details タブに移動し、下にスクロールして Advanced Properties セクションを展開します。Python library path に次のパスを追加します。
      s3://aws-blogs-artifacts-public/artifacts/BDB-4789/sap_odata_state_management.zip

    6. 次に Script タブを選択し、右上の Edit script を選択します。Confirm を選択して、ジョブがスクリプトのみであることを確認します。

デルタトークンを有効にするには、スクリプトに次の変更を加えてください。

    1. ステップ 5 で追加した SAP OData ステート管理ライブラリクラスをインポートするため、次のコードを 8 行目に追加します。
      from sap_odata_state_management.state_manager import StateManagerFactory, StateManagerType, StateType

    2. 次の数ステップでは、デルタトークンをジョブタグに取得して永続化し、後続のジョブ実行からアクセスできるようにします。デルタトークンは SAP ソースへの要求に追加され、増分変更が抽出されます。
      トークンが渡されない場合、ロードは初回ロードとして実行され、トークンが次回の実行用に永続化されます。その次の実行はデルタロードになります。

      sap_odata_state_management ライブラリを初期化するため、接続オプションを変数で定義して、ステートマネージャーでその変数の値を定義します。これを行うには、 job.init ステートメントの後 16 行目に次のコードを追加します。
      <key of MaterialMasterAttributes node> と  <entityName for Material Attribute> は、既存の生成されたスクリプトの # Script generated for node Material Master Attributes コードに値が入っているのでそこからコピーできます。適切な値に置き換えてください。
      key = "<key of MaterialMasterAttributes node>"
      state_manager = StateManagerFactory.create_manager(
          manager_type=StateManagerType.JOB_TAG, state_type=StateType.DELTA_TOKEN, options={"job_name": args['JOB_NAME'], "logger": glueContext.get_logger()}
      )
      options = {
          "connectionName": "GlueSAPOData",
          "entityName": "<entityName for Material Attribute>",
          "ENABLE_CDC": "true"
      }
      connector_options = state_manager.get_connector_options(key)
      options.update(connector_options)
      Code
    3. Material Master Attributes ノードに生成された既存のスクリプトの前に # を付け加えてコメントアウトし、次の置換スニペットを追加します。
       <key of MaterialMasterAttributes node> = glueContext.create_dynamic_frame.from_options(connection_type="sapodata", connection_options=options, transformation_ctx="<key of MaterialMasterAttributes node>")
      Code
    4. ダイナミックフレームからデルタトークンを読み取って、ジョブのタグに保存するには、スクリプトの最後の行 job.commit() の前に次のコードスニペットを追加します。
      state_manager.update_state(key, <key of MaterialMasterAttributes node>.toDF())
      Code

      最終的にスクリプトは次のようにになるイメージです。

      import sys 
       from awsglue.transforms import *
       from awsglue.utils import getResolvedOptions 
       from pyspark.context import SparkContext 
       from awsglue.context import GlueContext 
       from awsglue.job import Job 
       from awsglue.dynamicframe import DynamicFrame 
       from sap_odata_state_management.state_manager import StateManagerFactory, StateManagerType, StateType 
      
       args = getResolvedOptions(sys.argv, ['JOB_NAME'])
       sc = SparkContext()
       glueContext = GlueContext(sc)
       spark = glueContext.spark_session 
       job = Job(glueContext)
       job.init(args['JOB_NAME'], args)
      
       key = "MaterialMasterAttributes_node1730873953236"
       state_manager = StateManagerFactory.create_manager(
          manager_type=StateManagerType.JOB_TAG, state_type=StateType.DELTA_TOKEN, options={"job_name": args['JOB_NAME'], "logger": glueContext.get_logger()}
      )
       options = {
          "connectionName": "GlueSAPOData",
          "entityName": "/sap/opu/odata/sap/ZMATERIAL_ATTR_SRV/EntityOf0MATERIAL_ATTR",
          "ENABLE_CDC": "true"
      }
      
      # Script generated for node Material Group Text 
       MaterialGroupText_node1730874412841 = glueContext.create_dynamic_frame.from_options(connection_type="sapodata", connection_options={"ENABLE_CDC": "false", "connectionName": "GlueSAPOData", "FILTER_PREDICATE": "SPRAS = 'E'", "ENTITY_NAME": "/sap/opu/odata/sap/ZMATL_GROUP_SRV/EntityOf0MATL_GROUP_TEXT"}, transformation_ctx="MaterialGroupText_node1730874412841")
      
      # Script generated for node Material Master Attributes 
      #MaterialMasterAttributes_node1730873953236 = glueContext.create_dynamic_frame.from_options(connection_type="sapodata", connection_options={"ENABLE_CDC": "true", "connectionName": "GlueSAPOdata", "FILTER_PREDICATE": "limit 100", "SELECTED_FIELDS": "MATNR,MTART,MATKL,BISMT,ERSDA,DML_STATUS,DELTA_TOKEN,GLUE_FETCH_SQ", "ENTITY_NAME": "/sap/opu/odata/sap/ZMATERIAL_ATTR_SRV/EntityOf0MATERIAL_ATTR"}, transformation_ctx="MaterialMasterAttributes_node1732755261264")
       MaterialMasterAttributes_node1730873953236 = glueContext.create_dynamic_frame.from_options(connection_type="sapodata", connection_options=options, transformation_ctx="MaterialMasterAttributes_node1730873953236")
      
      # Script generated for node Change Schema 
       ChangeSchema_node1730875214894 = ApplyMapping.apply(frame=MaterialGroupText_node1730874412841, mappings=[("matkl", "string", "matkl2", "string"), ("txtsh", "string", "txtsh", "string")], transformation_ctx="ChangeSchema_node1730875214894")
      
      # Script generated for node Join 
       MaterialMasterAttributes_node1730873953236DF = MaterialMasterAttributes_node1730873953236.toDF()
       ChangeSchema_node1730875214894DF = ChangeSchema_node1730875214894.toDF()
       Join_node1730874996674 = DynamicFrame.fromDF(MaterialMasterAttributes_node1730873953236DF.join(ChangeSchema_node1730875214894DF, (MaterialMasterAttributes_node1730873953236DF['matkl'] == ChangeSchema_node1730875214894DF['matkl2']), "left"), glueContext, "Join_node1730874996674")
      
      # Script generated for node Amazon S3 
       AmazonS3_node1730875848117 = glueContext.write_dynamic_frame.from_options(frame=Join_node1730874996674, connection_type="s3", format="json", connection_options={"path": "s3://sapglueodatabucket", "compression": "snappy", "partitionKeys": []}, transformation_ctx="AmazonS3_node1730875848117")
       state_manager.update_state(key, MaterialMasterAttributes_node1730873953236.toDF())
       job.commit()
      
      Code
    5. 変更を保存するには、保存 ボタンを選択します。
    6. 実行 をクリックしてジョブを実行します。この時点は、ジョブの詳細タブにはタグがありません。
    7. ジョブの実行が正常に完了するまで待ちます。ステータスは 実行 タブで確認できます。
    8. ジョブの実行が完了すると、ジョブの詳細のタブでタグが追加されたことがわかります。次のジョブの実行では、このトークンを読み取り、デルタロードが実行されます。

SAP からのデータに対するクエリ

AWS Glue ジョブの実行により、Data Catalog にエントリが作成されたので、すぐにデータをクエリすることができます。

  1. Amazon Athena コンソールを開きます。
  2. Launch Query Editor を選択します。
  3. 適切なワークグループが割り当てられていることを確認するか、必要に応じて ワークグループを作成 します。
  4. sapgluedatabase を選択し、次のようなクエリを実行してデータの分析を開始します。
    select matkl, txtsh, count(*)
     from materialmaster 
     group by 1, 2 
     order by 1, 2 ;
    Code

クリーンアップ

追加料金が発生しないよう、このブログで使用した AWS リソースを削除します。削除するリソースは、AWS Glue ジョブ、SAP OData 接続先、Glue データカタログエントリ、Secrets Manager のシークレット、IAM ロール、S3 バケットに保存しているファイル、S3 バケットです。

結論

このブログでは、サーバーレスで複数の SAP データソースからのデータ抽出と差分抽出プロセスを作成する方法を説明しました。この方法では、AWS Glue を使用して SAP ODP デルタトークンを利用し、SAP ソースからデータを差分で抽出し、Amazon S3 にデータをロードしました。

AWS Glue はサーバーレスのサービスなので、インフラストラクチャの管理は不要で、ジョブの実行中に使用されたリソースに料金が発生します (データ保存先のストレージコストも発生します)。組織がますますデータドリブンになるにつれ、この SAP コネクタは、SAP ソースデータをビッグデータの分析やコストに効果的で高性能、且つセキュアに取り込むことができます。詳細は AWS Glue をご覧ください。

翻訳は Specialist SA トゥアンが担当しました。原文はこちらです。


著者について

Allison Quinn はメルボルン (オーストラリア) に拠点を置く Sr. ANZ Analytics Specialist Solutions Architect で、同地域の金融サービス顧客と密接に協力しています。Allison は SAP 製品で 15 年以上の経験があり、現在は AWS ネイティブサービスに分析技術の専門性を集中させています。データに関するすべてのことに情熱を持ち、あらゆる種類の顧客がビジネス上の利益を得られるようデータの民主化を目指しています。

Pavol は、AWS のイノベーションソリューションアーキテクトで、EMEA 地域における SAP クラウド導入を専門としています。20 年以上の経験を持ち、グローバル顧客の AWS への SAP システムの移行と最適化を支援しています。Pavol は、AWS のアジリティ、レジリエンシー、パフォーマンスを活用して、SAP 環境をクラウドに移行するための戦略を立案しています。顧客に対して、AWS の AI/ML、データ分析、アプリケーションサービスを利用して SAP ランドスケープを近代化し、インテリジェンス、自動化、パフォーマンスを向上させるのを支援しています。

Partha Pratim Sanyal は、カナダのバンクーバーにある AWS Glue のソフトウェア開発エンジニアで、データ統合、分析、接続に特化しています。豊富なバックエンド開発の専門知識を持ち、顧客中心のインパクトのある優れたソリューションを作ることに尽力しています。ユーザーがデータを簡単に分析・理解できるような機能を構築することに重点を置いています。Partha は、複雑なユーザーニーズに対処し、データのアクセシビリティと洞察力を高めるための直感的で価値のある体験を創出することに熱心です。

Diego は、SAP テクノロジーに 20 年以上の経験を持つエンタープライズソリューションアーキテクトで、SAP のイノベーション、データ分析に特化しています。パートナーとしても顧客としても働いた経験があり、システムと組織を販売、実装、運用するために必要なことを完全に理解しています。テクノロジーとイノベーションに情熱を持ち、顧客の成果とビジネス価値の提供に重点を置いています。

Luis Alberto Herrera Gomez は、バンクーバーの AWS Glue でソフトウェア開発エンジニアを務めています。バックエンドエンジニアリング、マイクロサービス、クラウドコンピューティングに特化しています。Amazon と AWS に入社する前に複数のスタートアップでバックエンドおよびフルスタック開発者を経験し、7 〜 8 年の経験があります。Luis は、スケーラブルで効率的なクラウドベースのアプリケーションの開発に注力しています。AWS テクノロジーに関する専門知識を活かし、複雑なデータ処理タスクを処理できる高性能システムを設計しています。Luis は、クラウドコンピューティングを活用して、難しいビジネス課題を解決することに情熱を持っています。