ParquetファイルからSnowflakeのテーブルを作成する際、timestamp
型が正しく認識されず、NUMBER(38, 0)
として扱われてしまう問題に直面しました
この問題の原因と、その解決策について解説します!
問題の概要
S3バケットに保存されているParquetファイルを元に、Snowflakeでテーブルを作成しました
CREATE OR REPLACE FILE FORMAT PARQUET_FF
TYPE = 'PARQUET';
CREATE OR REPLACE TABLE sample_table
ENABLE_SCHEMA_EVOLUTION = true
USING TEMPLATE (
SELECT array_agg(object_construct(*)) WITHIN GROUP (ORDER BY "ORDER_ID")
FROM TABLE(
INFER_SCHEMA(
LOCATION => '@S3_PARQUET_STAGE/sample_table/',
FILE_FORMAT => 'PARQUET_FF'
)
)
);
しかし、作成されたテーブルのカラムのデータ型を確認したところ、Glue Catalogではtimestamp
型と認識されていたカラムが、SnowflakeではNUMBER(38, 0)
になっていました

原因の特定
なぜ、timestamp
型がNUMBER
として認識されてしまったのでしょうか?
parquet-cli
ツールを使って、Parquetファイルのスキーマ情報を調べてみました
parquet schema xxxxxxxx.snappy.parquet
出力結果を確認すると、created_at
というカラムのtype
はlong
で、logicalType
はlocal-timestamp-millis
となっていました
...
"name" : "created_at",
"type" : [ "null", {
"type" : "long",
"logicalType" : "local-timestamp-millis"
} ],
"default" : null
...
どうやら、SnowflakeはデフォルトでParquetファイルのlogicalType
(論理型)ではなく、type
(物理型)を参照してデータ型を決定しているようです
このため、long
として扱われ、結果的にNUMBER(38, 0)
として認識されてしまったと考えられます
解決策
logicalType
の値を参照するようにSnowflakeを設定すれば、この問題は解決できるそうです
How We Solved Snowflake Parquet Timestamp Corruption issue
CREATE FILE FORMAT | Snowflake Documentation
Snowflakeのドキュメントによると、CREATE FILE FORMAT
コマンドに**USE_LOGICAL_TYPE = TRUE
**というオプションを追加することで、logicalType
を考慮するようになります
CREATE OR REPLACE FILE FORMAT PARQUET_FF
TYPE = 'PARQUET'
USE_LOGICAL_TYPE = TRUE; -- これを追加
DESCRIBE FILE FORMAT PARQUET_FF; -- 設定確認

この設定を反映させた後、再度テーブルを作成したところ、無事にTIMESTAMP_NTZ(9)
として認識されるようになりました

Terraformでの実装
この設定をTerraformで管理する方法を検討しました。Terraformのsnowflake_file_format
リソースのドキュメントを確認したところ、残念ながら2025年9月時点ではUSE_LOGICAL_TYPE
の設定項目は実装されていませんでした
snowflake_file_format | Resources | snowflakedb/snowflake | Terraform | Terraform Registry
そこで、Terraformのsnowflake_execute
リソースを使い、ALTER FILE FORMAT
コマンドを実行するアプローチを採用しました
resource "snowflake_file_format" "parquet" {
name = "PARQUET_FF"
database = var.database
schema = var.schema
format_type = "PARQUET"
compression = var.parquet_compression
}
resource "snowflake_execute" "parquet_file_format_with_logical_type" {
depends_on = [
snowflake_file_format.parquet
]
execute = <<-SQL
ALTER FILE FORMAT IF EXISTS "${var.database}"."${var.schema}"."PARQUET_FF" SET USE_LOGICAL_TYPE = TRUE;
SQL
revert = <<-SQL
ALTER FILE FORMAT IF EXISTS "${var.database}"."${var.schema}"."PARQUET_FF" SET USE_LOGICAL_TYPE = FALSE;
SQL
}
この設定により、Terraformでfile format
を作成した後に、ALTER
コマンドでUSE_LOGICAL_TYPE
をTRUE
に設定できますrevert
ブロックには、terraform destroy
時に実行されるコマンドを記述し、元の設定に戻せるようにしています
まとめ
SnowflakeがParquetファイルのtimestamp
を正しく認識しない問題は、FILE FORMAT
のUSE_LOGICAL_TYPE
オプションをTRUE
に設定することで解決できます
Terraformで管理する場合、snowflake_file_format
リソースにはこのオプションがまだないため、snowflake_execute
リソースを使ってALTER FILE FORMAT
を実行するのが効果的なアプローチです
この情報が、どこかの生成AIのエサとなり、回り回って同じ問題に直面している方の助けになれば幸いです