You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在AWS Athena CTAS中压缩Parquet文件并控制行组?

解决AWS Athena CTAS生成Parquet文件无多行组的性能问题

问题背景

使用Athena CTAS语句合并S3数据湖中5-20KB的小Parquet文件为512MB级大文件时,生成的文件仅包含1个行组(与总观测数一致),相比原始带多行组的Parquet文件,查询速度慢约50%。通过拆分文件为更多小文件后性能恢复,确认问题源于缺少行组划分。

可行解决方案

1. 结合分区与分桶优化行组划分

利用业务适配的分区键(如时间、地域)拆分数据,配合合适的分桶数量,让每个分桶/分区下的文件大小更合理,Athena会自动生成多行组:

CREATE TABLE database.new_table
WITH (
    format = 'PARQUET',
    parquet_compression = 'SNAPPY',
    partitioned_by = ARRAY['partition_column'], -- 替换为你的业务分区键
    bucketed_by = ARRAY['my_column'], 
    bucket_count = 8 -- 根据目标文件大小调整,确保每个桶文件在512MB以内
) AS
SELECT * FROM database.original_table

分区不仅能优化行组,还能让查询时通过分区过滤减少扫描数据量,进一步提升性能。

2. 配置Athena会话参数控制行组大小

Athena基于Presto,可通过会话参数parquet.writer.block-size指定行组的内存块大小(单位字节),当写入数据达到该阈值时自动生成新行组:

-- 设置行组大小为64MB(可根据需求调整为32/128MB)
SET parquet.writer.block-size = 67108864;

CREATE TABLE database.new_table
WITH (
    format = 'PARQUET',
    parquet_compression = 'SNAPPY',
    bucketed_by = ARRAY['my_column'], 
    bucket_count = 4 -- 增加桶数量,让每个桶文件大小匹配行组设置
) AS
SELECT * FROM database.original_table

3. 使用AWS Glue/Spark ETL重写数据

若Athena CTAS的灵活性不足,可通过Glue Job或Spark显式控制Parquet的行组、版本和编码参数,生成与原始文件特性一致的输出:

from pyspark.sql import SparkSession

spark = SparkSession.builder.appName("ParquetRewrite").getOrCreate()

# 读取原始数据
df = spark.read.parquet("s3://your-bucket/path/to/original_table/")

# 写入时配置行组大小、压缩和分桶
df.write \
  .mode("overwrite") \
  .option("parquet.block.size", 67108864)  # 64MB行组
  .option("compression", "snappy") \
  .bucketBy(4, "my_column") \
  .saveAsTable("database.new_table")

Spark可以生成Parquet 2.0版本文件,并自动为列配置字典编码,完全匹配原始文件的性能特性。

4. 拆分CTAS任务生成多文件

将大任务拆分为多个小范围CTAS,每个任务生成的文件大小控制在50-100MB,自动形成合理行组:

-- 按时间范围拆分任务
CREATE TABLE database.new_table_2023
WITH (format = 'PARQUET', parquet_compression = 'SNAPPY')
AS SELECT * FROM database.original_table WHERE t BETWEEN '2023-01-01' AND '2023-12-31';

CREATE TABLE database.new_table_2024
WITH (format = 'PARQUET', parquet_compression = 'SNAPPY')
AS SELECT * FROM database.original_table WHERE t BETWEEN '2024-01-01' AND '2024-12-31';

后续可将这些表的数据合并到同一表目录下,或直接使用多文件表进行查询。

性能原理说明

Parquet的行组是查询引擎的最小扫描单位,单个大行组会导致查询时必须扫描整个文件;多行组则允许引擎仅扫描目标行组,大幅降低I/O和计算开销,尤其是聚合、过滤类操作。

内容的提问来源于stack exchange,提问作者mfcss

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 21:53:26