こんにちは
データウェアハウス開発部 データレイクグループの大塚です。
ユーザ部門の方でも、AWSマネージメントコンソールの操作だけで要件を実現できないかチャレンジした結果、あと一歩のところでうまくいかなかった失敗談を紹介したいと思います。
自動化技術に頼りすぎると痛い目を見るよという参考になれば幸いです。
要件
ユーザ部門の方から下記2点の要望を受けました。
- 納品方式を
OneDrive
からS3
に変更するタイミングでAthena
で利用できるようにしたい - すぐに利用できるようにしたい
AsIs
OneDrive
に納品された最大150ファイル程度のCSVをダウンロードして利用している
ToBe
S3
に納品されたファイルをAthena
で分析できるようにしたい
構成案
下記の理由から、ユーザ部門の方と相談の上で、ノーコードで要件を実現できるGlue Crawler
を採用しました。
- 時間をかけずに要件を実現する必要がある
- 100件超あるファイルをテーブル化する処理を手動でやるのは大変
- できる限りユーザ部門で運用を完結できるようにしたい
Glue Crawler
の設定はエンジニアのサポートが必要
理想は「手順だけ作ってその手順をもとに誰でもすべての設定ができる」です
一見すると成功だが・・・
下記の通りAWSマネージメントコンソールのウィザードに従い、ユーザ部門の方と一緒に設定してみました。
- Set crawler properties
- Choose data sources and classifiers
- Configure security settings
- Set output and scheduling
- Review and create
実行したところあっさり成功!!
Athena
上でもデータを取得できているようです。
簡単に実現できてGlue Crawler
最高と思っていたのですが、後日ユーザ部門の方から一部テーブルがうまく読めてないと問い合わせがあり、調べてみると1行目にヘッダー行が含まれてしまっているテーブルがいくつかありました。
例.ヘッダー行が1行目に含まれる
col0 | col1 | col2 |
---|---|---|
項目名イ | 項目名ロ | 項目名ハ |
xxx | ○○○ | あいうえお |
yyy | □□□ | かきくけこ |
原因
データ行がすべて文字列の場合に、ヘッダー行を認識できない仕様のようです。
公式ページには下記の記載がありました。
(公式ページから引用)
ヘッダー行は、データ行と十分に異なっている必要があります。 これを判断するには、1 つ以上の行が STRING 型以外として解析されることを確認します。 すべての列が STRING 型である場合、最初のデータ行は以降の行と十分に異なっていないため、 ヘッダーとして使用できません。
ここからが茨の道の始まりです。
いくつか代替案は見つかるものの採用には至りませんでした。
代替案1(Classfier【分類子】を使う)
Column headings
オプションにHas Headings
を設定する
採用しなかった理由
Has Headings
オプションは列名をカンマ,
区切りで明示的に指定する必要があり、列数やヘッダー列が同じテーブルが複数あるケースにしか使えない
代替案2(1行目をスキップするオプションの追加)
- あとから
SQL
でヘッダー行を認識できていないテーブルに対して1行目をスキップするオプションを追加する
ALTER TABLE [tablename] SET TBLPROPERTIES ('skip.header.line.count' = '1');
採用しなかった理由
- あとから
SQL
を実行する手間が増える - 列名が
col0
~coln
となり使いづらい
結果どうしたか
ノーコードを諦めてGlue ETL Jobs
で簡単なETL
ジョブを作成することで実現しました。
実際コーディング作業はAI生成コードをほぼ採用する形で作成したのですが、
こちらもAIに頼りすぎてうまくいかなかった例を載せておきます。
AIコードの罠
AIへのインプット
Glueで特定のバケット配下にあるCSVを解析して1行目をタイトル列にしてDDLを生成してテーブル作成するスクリプトのサンプルをください
AIのアウトプット(一部省略)
import boto3 from pyspark.sql import SparkSession # 前半 # 特定パス配下のCSVをDataFrameで読込みながら型を取得してDDLを生成 # SparkSession の作成 spark = SparkSession.builder.getOrCreate() # CSV ファイルのパス bucket_name = 'your-bucket-name' prefix = 'path/to/your/csv/files' # S3 から CSV ファイルを読み込む s3_path = f"s3://{bucket_name}/{prefix}" df = spark.read.format("csv").option("header", "true").option("inferSchema", "true").load(s3_path) # CSV ファイルのヘッダーを取得 headers = df.columns # DDL を生成する ddl = f"CREATE EXTERNAL TABLE IF NOT EXISTS your_table_name (\n" for header in headers: data_type = df.schema[header].dataType.typeName() ddl += f" {header} {data_type},\n" ddl = ddl.rstrip(",\n") + "\n) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' LOCATION 's3://{bucket_name}/{prefix}';" # 後半 # AWS Glue にテーブルを作成(一部省略) glue_client = boto3.client('glue') database_name = 'your_database_name' table_name = 'your_table_name' table_input = { 'Name': table_name, 'StorageDescriptor': { 'Location': f"s3://{bucket_name}/{prefix}", 'InputFormat': 'org.apache.hadoop.mapred.TextInputFormat', 'OutputFormat': 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat' }, 'TableType': 'EXTERNAL_TABLE' } glue_client.create_table(DatabaseName=database_name, TableInput=table_input)
コードを見て間違いに気づいた方はいたでしょうか。
よく見ると前半で生成したDDL
を後半のテーブル作成で利用していないですね。
このコードを動かせるようにして実行したら、列がないテーブル名だけのテーブルが完成しました。
AI的には、2つの要件があると解釈した上でそれぞれ別の手法で提案して、 結果を1つのコードで返したという動きに見えました。
- 前半:
CSVから1行目をヘッダーとしたDDLを生成する
- 後半:
GlueでCSVからテーブルを作成する
追加対応
最終的には、追加でDDL
をAthena
上で実行してテーブルを作成するコードを追加して完成となりました。
追加コード
athena = boto3.client('athena') response = athena.start_query_execution( QueryString=ddl, QueryExecutionContext={ 'Database': f"{database_name}" }, ResultConfiguration={ 'OutputLocation': f"s3://{bucket_name}/query_results/" } )
前述のGlue Crawler
で作成したIAM Role
にAthena
の実行権限を付与
理想は「Glue
の権限のみで実現する」ですが、今回はこれ以上時間をかけられなかったのでこの対応としました。
実際には他にもS3
の特定パス配下のオブジェクト数分繰り返すコードも追加
まとめ
CSVの1行目を確実にヘッダーとして利用したい場合はGlue Crawlerではできない
生成AIのコードは自力で修正できるかつ複数のコードをつなげるプログラミングスキルが必要
最後に
今回は失敗しましたが、スピーディに要件が実現できるのは自動化技術の強みであり、成功すればユーザ/システム部門がお互いに幸せになれるため、めげずに積極的にチャレンジしていきたいです。
また、構成案の採用理由で、ユーザ部門の方で運用を完結可能としているものの、AWSマネージメントコンソールを操作したりAthena
でSQL
を操作したりと、スキルのある方だから提案できた構成でした。
今回提案した構成を実際に設定手順としてまとめて、今後運用していくユーザ部門の方に改めて感謝しつつ終わりたいと思います。
最後まで、お読みいただきありがとうございました。
JMDCでは、ヘルスケア領域の課題解決に一緒に取り組んでいただける方を積極採用中です!詳細は下記の募集一覧からご確認ください。 hrmos.co まずはカジュアルにJMDCメンバーと話してみたい/経験が活かせそうなポジションの話を聞いてみたい等ございましたら、下記よりエントリーいただけますと幸いです。 hrmos.co ★最新記事のお知らせはぜひ X(Twitter)、またはBlueskyをご覧ください! Tweets by jmdc_tech twitter.com bsky.app