😵‍💫

BigQueryでParquet出力したファイルをRedshift Spectrumで読み込む際のつまずきポイント

2024/12/12に公開

はじめに

こんにちは。レンティオ株式会社でエンジニアをしているMasaruTechです。
このエントリは AWS Analytics Advent Calendar 2024 の12日目の記事です。

今回は、BigQueryのデータをParquet形式で出力してRedshift Spectrumで読み込もうとした時にいくつかつまずきポイントがあったのでその紹介をしようと思います。

Parquetとは

正式名称は Apache Parquet です。
詳しい説明はここでは省きますが、CSVのような行指向と違い列指向データファイルなのでRedshift SpectrumでS3からファイルを読み込む時にテキストファイル形式より効率よく処理できます。

AWSのドキュメントにもクエリパフォーマンスを向上させる方法のところで記載があります。
https://docs.aws.amazon.com/ja_jp/redshift/latest/dg/c-spectrum-external-performance.html

Redshift Spectrum のパフォーマンスは次の方法で向上させることができます。

  • Apache Parquet 形式のデータファイルを使用します。Parquet は列形式でデータを保存するため、Redshift Spectrum は不要な列をスキャンから削除できます。データがテキストファイル形式である場合、Redshift Spectrum はファイル全体をスキャンする必要があります。

つまずきポイント

BigQueryのINTEGER型はRedshiftではBIGINT型

Redshiftの整数型はSMALLINT/INTEGER/BIGINTと細かくありますが、BigQueryではINTEGER型のみです。
INTEGER型なのでRedshiftでも同じINTEGERにしても相手はBIGINT(INT64)相当なのでエラーになります。

error: Spectrum Scan Error code: 15007 context: File 'https://s3.ap-northeast-1.amazonaws.com/xxx/yyy.parquet' has an incompatible Parquet schema for column 's3://xxx/yyy.id'.

BIGNUMERIC型はそのままではRedshiftでは扱えない

BIGNUMERIC型のカラムをParquet出力するとParquetでの型はFIXED_LEN_BYTE_ARRAY[32]になります。
RedshiftにはBIGNUMERIC相当の型がないのでDECIMALやDOUBLE PRECISIONにしてみましたが、RedshiftではFIXED_LEN_BYTE_ARRAY[16]までしか扱えないようで下記のようなエラーになります。

Cannot decode Decimal from FIXED_LEN_BYTE_ARRAY of length 32. The length should be positive and not exceed 16.

これはもうBIGNUMERICの精度を保って読み込むことはできないので、精度が落ちることを妥協するか諦めるしかありません。
今回はNUMERIC相当にしても問題ないとのことだったので、BigQuery側でParquet出力する際にキャストしたカラムも出力してそれを利用するようにしました。

EXPORT DATA
  OPTIONS (
    uri = 'gs://xxx/yyy.parquet',
    format = 'Parquet'
    )
AS (
  SELECT *, cast(bignumeric_column as NUMERIC) as cast_bignumeric_column
  FROM xxx.yyy
);

完全なエラーメッセージの見方がわからない

Redshift Spectrumでエラーが起きた時、エラーメッセージが長すぎるとコンソール上の表示は途中で切り捨てられている場合があります。
https://docs.aws.amazon.com/ja_jp/redshift/latest/dg/c-spectrum-troubleshooting.html

エラーメッセージは、メッセージの長さ制限で切り捨てられている場合もあります。

省略されていても列名まではだいたい分かるのでそこまで困っているわけではないのですが、いまだにこの完全なエラーメッセージを見るにはどうしたらよいか分かっていないです。
もし知っている方いたらコメントなどで教えていただけるとうれしいです。

https://docs.aws.amazon.com/ja_jp/redshift/latest/dg/c-spectrum-troubleshooting.html

Redshift Spectrum クエリで生成されたエラーを表示するには、SVL_S3LOGシステムテーブルのクエリを実行します。

ドキュメントにはこのように説明がありますが、SVL_S3LOGはプロビジョニングのRedshiftのみで今回はRedshift Serverlessを利用しているため参照できないです。
さらにドキュメントを漁っていると SYS_EXTERNAL_QUERY_ERROR というそれっぽいシステムビューがあったのですが、これにアクセスしても空っぽで何も取得できませんでした。
https://docs.aws.amazon.com/ja_jp/redshift/latest/dg/SYS_EXTERNAL_QUERY_ERROR.html

システムビュー SYS_EXTERNAL_QUERY_ERROR をクエリして Redshift Spectrum のスキャンエラーに関する情報を取得できます。

Stack Overflowでも同様の質問がありましたが、有力な情報は記事公開時でもない状況です。
https://stackoverflow.com/questions/77062396/how-do-i-get-the-details-about-a-spectrum-scan-error-on-an-external-table-on-red

現状これで困っているわけではないのでよいのですが、気にはなるので暇を見つけてもう少し調べてみようと思います。

まとめ

Parquet形式なので簡単にRedshiftでも読み込めるようになると考えていたのですが、BigQueryとRedshiftのデータ型の違いに初めは少し苦戦しました。
数をこなすごとにだんだんと勘所を覚えてきたり、parquet-cliのようなツールの使い方も覚えたのでよい経験になりました。

レンティオではRedshift Serverlessをバリバリ使っていこうと考えているので、そのあたりの知見もたまったら今後ブログにしたいと思っています。

採用情報

レンティオでは絶賛、エンジニアを募集しています!
https://recruit.rentio.co.jp/engineer

Discussion