Cloud Storage 上の Parquet ファイルのスキーマ情報をメタデータのみで取得する
Google Cloud データエンジニアのはんざわです。
今回のブログでは、Cloud Storage にある Parquet ファイルのメタデータのみにアクセスし、物理データ型と論理データ型のスキーマ情報を取得する方法を紹介します。
Parquet ファイルのスキーマ情報を取得する方法はいくつかありますが、ファイル全体を読み込む方法は、特に大規模なファイルの場合、時間とコストがかかります。スキーマ情報だけが必要な場合は、メタデータのみを読み込むことで、より効率的に処理できます。
本記事で紹介する方法は、以下の S3 版の記事を Cloud Storage 向けに変更したものです。Parquet のデータ構造や実装方針については、以下のブログを確認してください。
やってみた
検証には、BigQuery の公開データセットである bigquery-public-data.hacker_news.full
を使用しました。
今回用意した Python スクリプトは以下の通りです。
import io
import pyarrow.parquet as pq
from google.cloud import storage
def get_blob(bucket_name, blob_path):
"""指定したバケットとパスでオブジェクトを取得"""
gcs_client = storage.Client()
bucket = gcs_client.bucket(bucket_name)
return bucket.blob(blob_path)
def get_parquet_metadata(blob):
"""Parquet ファイルのメタデータを取得"""
footer_length = 8 # Parquetのフッターサイズ
# Parquetのフッター情報を取得
footer_bytes = blob.download_as_bytes(start=-footer_length)
# フッターの最初の4バイトからメタデータのサイズを取得
metadata_length = int.from_bytes(footer_bytes[:4], "little")
# メタデータの開始位置からメタデータ部分のみ取得
metadata_bytes = blob.download_as_bytes(start=-(metadata_length + footer_length), end=-footer_length)
return io.BytesIO(metadata_bytes)
def main():
bucket_name = "cm-hanzawa-parquet"
blob_name = "hacker-news/000000000000.parquet"
blob = get_blob(bucket_name, blob_name)
metadata_stream = get_parquet_metadata(blob)
# Parquetのメタデータを取得
parquet_metadata = pq.read_metadata(metadata_stream)
# 物理型 & 論理型の取得
print("カラム名: 物理型, 論理型")
for column in parquet_metadata.schema:
print(f"{column.name}: {column.physical_type} ({column.logical_type})")
if __name__ == "__main__":
main()
- 実行した結果
カラム名: 物理型, 論理型
title: BYTE_ARRAY, (String)
url: BYTE_ARRAY, (String)
text: BYTE_ARRAY, (String)
dead: BOOLEAN, (None)
by: BYTE_ARRAY, (String)
score: INT64, (None)
time: INT64, (None)
timestamp: INT64, (Timestamp(isAdjustedToUTC=false, timeUnit=microseconds, is_from_converted_type=false, force_set_converted_type=false))
type: BYTE_ARRAY, (String)
id: INT64, (None)
parent: INT64, (None)
descendants: INT64, (None)
ranking: INT64, (None)
deleted: BOOLEAN, (None)
Parquet ファイル全体を直接読み込んでスキーマ情報を取得し、結果を比較してみます。
import pyarrow.parquet as pq
parquet_file = pq.ParquetFile('hacker_news_full.parquet')
print("カラム名: 物理型, 論理型")
for column in parquet_file.metadata.schema:
print(f"{column.name}: {column.physical_type}, ({column.logical_type})")
- 実行した結果
カラム名: 物理型, 論理型
title: BYTE_ARRAY, (String)
url: BYTE_ARRAY, (String)
text: BYTE_ARRAY, (String)
dead: BOOLEAN, (None)
by: BYTE_ARRAY, (String)
score: INT64, (None)
time: INT64, (None)
timestamp: INT64, (Timestamp(isAdjustedToUTC=false, timeUnit=microseconds, is_from_converted_type=false, force_set_converted_type=false))
type: BYTE_ARRAY, (String)
id: INT64, (None)
parent: INT64, (None)
descendants: INT64, (None)
ranking: INT64, (None)
deleted: BOOLEAN, (None)
メタデータのみにアクセスして取得したスキーマ情報と、ファイル全体を読み込んで取得したスキーマ情報が一致することを確認できました。
まとめ
今回のブログでは、Cloud Storage にある Parquet ファイルのメタデータのみにアクセスし、物理データ型と論理データ型のスキーマ情報を取得してみました。
メタデータのみを取得しているため、ファイル全体を読み込むよりもメモリ効率が良くなります。
前回のブログで紹介した通り、Parquet ファイルを BigQuery で扱う場合、データの読み込みが非常に早く優れています。
その一方で、データ型に少しクセがあり、Parquet のスキーマ情報に合わせて、BigQuery のテーブル定義も紐づける必要があります。詳細については、以下のドキュメントをご確認ください。
参考:Parquet の変換
今回紹介したスクリプトが参考になれば幸いです。