AWS Athena两表INNER JOIN高效查询方案对比及内存问题咨询
Amazon Athena 大表INNER JOIN优化及两种写法效率分析
两种JOIN写法的效率差异
Athena基于Presto引擎,默认情况下两种写法的执行效率几乎无差异:
- 方法1的WITH子句(未加
MATERIALIZED关键字)会被优化器直接内联到主查询中,和方法2的直接JOIN生成完全一致的执行计划。只有当WITH子查询被多次引用时,才会触发物化产生性能差异,而你的场景中都是单次引用,所以写法本身不影响效率。
内存不足的核心原因及优化方案
两种方法都崩溃的问题,本质不是写法问题,而是JOIN阶段的内存负载过高,结合Athena特性和你的场景,可从以下方向优化:
1. 预解析JSON字段,避免JOIN时实时计算
你当前在查询时动态解析event字段的JSON内容,会在JOIN阶段产生大量临时计算和内存占用。建议用**CTAS(Create Table As Select)**将常用字段提前物化到列式存储表(如Parquet)中:
-- 预处理表A,提取需要的字段并存储为Parquet CREATE TABLE tableA_parquet WITH (format = 'PARQUET', partitioned_by = ARRAY['companyId']) AS SELECT id, json_format(json_extract(event, '$.data.resource.companyId')) as companyId, json_extract_scalar(event, '$.XX') as XX, json_extract_scalar(event, '$.YY') as YY FROM tableA WHERE -- 先做初步过滤,减少数据量 your_tableA_filter_conditions; -- 同理预处理表B CREATE TABLE tableB_parquet WITH (format = 'PARQUET', partitioned_by = ARRAY['companyId']) AS SELECT id, json_format(json_extract(event, '$.data.resource.companyId')) as companyId, json_extract_scalar(event, '$.WW') as WW, json_extract_scalar(event, '$.ZZ') as ZZ FROM tableB WHERE your_tableB_filter_conditions;
预处理后JOIN直接使用预解析的字段,无需实时解析JSON,内存开销会大幅降低。
2. 利用分区/分桶优化JOIN策略
- 分区裁剪:按
companyId分区后,JOIN时会只处理匹配的分区数据,减少参与JOIN的总行数,逻辑和Spark的分区裁剪一致。 - 分桶JOIN:对于超大规模表,按JOIN键
id分桶,Athena可以在分桶级别做局部JOIN,避免全表shuffle:CREATE TABLE tableA_bucketed WITH ( format = 'PARQUET', bucketed_by = ARRAY['id'], bucket_count = 100 -- 根据数据量调整,建议取10-200之间 ) AS SELECT id, companyId, XX, YY FROM tableA_parquet; -- 同理创建表B的分桶表
3. 严格控制JOIN的数据量
- 确保过滤条件(你Python函数中存储的查询)被谓词下推到数据源层面,提前过滤掉无关数据,比如时间范围、无效companyId等,减少参与JOIN的行数。
- 绝对避免
SELECT *,只查询需要的字段(如方法2中的a.XX, a.YY, b.WW, b.ZZ),减少内存中加载的数据量。
4. 调整Athena会话参数优化内存分配
通过设置会话参数调整执行策略和内存配额:
-- 对于大表JOIN,使用分区式分发替代默认的广播分发 SET session join_distribution_type = 'PARTITIONED'; -- 增加单个任务的内存配额(最大支持16GB) SET session memory_usage_per_task = '8GB'; -- 调整任务并发数,避免内存竞争 SET session task_concurrency = '10';
内容的提问来源于stack exchange,提问作者Henri J
相关产品推荐
相关产品推荐

