Cloud Storage 上の Parquet ファイルのスキーマ情報をメタデータのみで取得する

Cloud Storage 上の Parquet ファイルのスキーマ情報をメタデータのみで取得する

Clock Icon2025.02.14

Google Cloud データエンジニアのはんざわです。

今回のブログでは、Cloud Storage にある Parquet ファイルのメタデータのみにアクセスし、物理データ型と論理データ型のスキーマ情報を取得する方法を紹介します。

Parquet ファイルのスキーマ情報を取得する方法はいくつかありますが、ファイル全体を読み込む方法は、特に大規模なファイルの場合、時間とコストがかかります。スキーマ情報だけが必要な場合は、メタデータのみを読み込むことで、より効率的に処理できます。

本記事で紹介する方法は、以下の S3 版の記事を Cloud Storage 向けに変更したものです。Parquet のデータ構造や実装方針については、以下のブログを確認してください。

https://dev.classmethod.jp/articles/s3-parquet-get-schema-data/

やってみた

検証には、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 で扱う場合、データの読み込みが非常に早く優れています。

https://dev.classmethod.jp/articles/bigquery-parquet-csv/

その一方で、データ型に少しクセがあり、Parquet のスキーマ情報に合わせて、BigQuery のテーブル定義も紐づける必要があります。詳細については、以下のドキュメントをご確認ください。

参考:Parquet の変換

今回紹介したスクリプトが参考になれば幸いです。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.