Athena 中的性能优化 - Amazon Athena
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 Amazon Web Services 服务入门

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

Athena 中的性能优化

本主题提供了一般信息和具体建议,以便在您拥有大量数据并遇到内存使用情况或性能问题时改进 Athena 的性能。

物理限制

通常,Athena 将每个查询的运行时间限制为 30 分钟。超出此限制的查询将自动取消,免费。如果查询内存不足或节点在处理过程中崩溃,可能会发生如下错误:

INTERNAL_ERROR_QUERY_ENGINE
EXCEEDED_MEMORY_LIMIT: Query exceeded local memory limit
Query exhausted resources at this scale factor
Encountered too many errors talking to a worker node. The node may have crashed or be under too much load.

查询优化技术

对于需要超出现有限制的资源的查询,您可以优化查询或重新构建要查询的数据。要优化查询,请考虑本节中的建议。

数据大小

避免单个大文件— 单个文件加载到单个节点中进行处理。如果您的文件大小非常大,请尝试将文件分解为较小的文件并使用分区来组织它们。

一次读取更少量的数据— 一次扫描大量数据可能会降低查询速度并增加成本。使用分区或筛选器限制要扫描的文件。

避免列过多— 消息通用 _ 内部 _ 错误:IO.Airlift.字节编译异常当 Athena 无法将查询编译为字节码时,可能会发生。此异常通常是由于查询中的列太多引起的。减少查询中的列数或创建子查询并使用JOIN,它可以检索较少量的数据。

避免大量查询输出— 由于查询结果是通过单个 Athena 节点写入 Amazon S3 的,因此大量的输出数据会降低性能。要解决此问题,请尝试使用CTAS创建一个包含查询结果的新表,或者INSERT INTO将新结果附加到现有表中。

避免使用大输出的 CTAS 查询— 由于输出数据是由单个节点写入的,因此 CTAS 查询也可以占用大量内存。如果要输出大量数据,请尝试将任务分成较小的查询。

如果可能,避免有大量的小文件— Amazon S3 拥有limit每秒 5500 个请求。Athena 查询共享相同的限制。如果您需要在单个查询中扫描数百万个小对象,则 Amazon S3 可以轻松限制您的查询。要避免过度扫描,请使用Amazon GlueETL 定期压缩文件或对表进行分区并添加分区键过滤器。有关更多信息,请参阅 。以较大的组读取输入文件中的Amazon Glue开发人员指南或如何配置Amazon GlueETL 工作输出更大的文件?中的Amazon知识中心。

避免扫描整个表— 使用下面的技术避免扫描整个表:

  • 限制使用”*“。除非必要,否则尽量不要选择所有列。

  • 避免在同一查询中多次扫描同一个表

  • 使用筛选条件减少要扫描的数据量。

  • 在可能的情况下,添加LIMIT子句。

避免在单个查询中引用多个视图和表— 由于具有许多视图和/或表的查询必须将大量数据加载到单个节点,因此可能会发生内存不足错误。如果可能,请避免在单个查询中引用过多的视图或表。

避免大型 JSON 字符串— 如果数据存储在单个 JSON 字符串中,并且 JSON 数据的大小很大,则在处理 JSON 数据时可能会发生内存不足错误。

文件格式

使用高效的文件格式,如镶木地板或 ORC— 要显著减少查询运行时间和成本,请使用压缩的镶木地板或 ORC 文件来存储数据。要在 Athena 中将现有数据集转换为这些格式,可以使用 CTAS。有关更多信息,请参阅将 CTAS 和 INSERT INTO 用于 ETL 和数据分析

ORC 格式和镶木格式之间切换— 经验表明,同一组数据在处理时间方面可能有显著差异,具体取决于它是以 ORC 还是镶木格式存储。如果遇到性能问题,请尝试其他格式。

HIDION 查询— 由于HIDION 查询绕过镶木地板格式文件的本地读取器和拆分生成器,它们可能会很慢。查询 Hudi 数据集时,请记住这一点。

联接、分组和联合

减少内存密集型操作的使用— 操作类似JOINGROUP BYORDER BY, 和UNION都需要将大量数据加载到内存中。要加快查询速度,请找到其他方法来实现相同的结果,或者添加类似LIMIT添加到外部查询中。

考虑使用 UNION ALL— 为了消除重复,UNION构建一个散列表,这会消耗内存。如果您的查询不需要消除重复项,请考虑使用UNION ALL获得更好的性能。

使用 CTAS 作为加速 JOIN 操作的中间步骤— 使用 CTAS 将中间数据保存到 Amazon S3 中,而不是在每个查询中加载和处理中间数据。这可以帮助加快操作的性能,如JOIN

Partitioning

限制表中的分区数— 当表具有超过 100,000 个分区时,查询可能会很慢,因为发送到Amazon Glue检索分区信息。要解决此问题,请尝试使用下列选项之一:

删除旧分区,即使它们是空的— 即使分区为空,分区的元数据仍然存储在Amazon Glue。加载这些不需要的分区可能会增加查询运行时间。要删除不需要的分区,请使用ALTER TABLE DROP PARTITION

查找单个分区— 查找单个分区时,请尝试提供所有分区值,以便 Athena 可以通过一次调用Amazon Glue。否则,Athena 必须检索所有分区并过滤它们。这可能成本高昂,并大大增加查询的规划时间。如果您有可预测的分区模式,则可以使用分区投影以避免分区查找调用Amazon Glue。

设置合理的分区投影属性— 使用分区投影,Athena 会尝试为每个分区名称创建一个分区对象。因此,请确保您定义的表属性不会创建近乎无限数量的可能分区。

若要频繁添加新分区,请使用ALTER TABLE ADD PARTITION— 如果您使用MSCK REPAIR TABLE以频繁添加新分区(例如,每天)并遇到查询超时,请考虑使用ALTER TABLE ADD PARTITIONMSCK REPAIR TABLE最适用于首次创建表或在数据和分区元数据之间存在奇偶校验的不确定性时。

避免在带有分区列的 WHERE 子句中使用 coalesce ()— 在某些情况下,使用合并 ()或其他函数WHERE子句可能会导致性能降低。如果发生这种情况,请尝试重写查询以提供相同的功能,而不使用coalesce()

开窗函数

最大限度地减少窗口函数的使用窗口函数例如等级 ()是内存密集型的。通常,窗口函数需要将整个数据集加载到单个 Athena 节点以进行处理。对于非常大的数据集,这可能会导致节点崩溃。要避免出现此情况,请尝试使用下面的选项:

  • 筛选数据并对数据的子集运行窗口函数。

  • 使用PARTITION BY子句与窗口函数一起使用。

  • 找到构建查询的替代方法。

使用更高效的函数

Replacerow_number() OVER (...) as rnk ... WHERE rnk = 1— 若要加快查询的速度行数 ()子句,将此语法替换为GROUP BYORDER BY, 和LIMIT 1

使用正则表达式而不是LIKE大字符串— 包含子句的查询,例如LIKE '%string%'可能会非常昂贵。考虑使用类似于正则表达式 ()函数和正则表达式。

使用最大值()而不是元素在(数组排序(),1)— 为了提高速度,请替换嵌套函数element_at(array_sort(), 1)替换为MAX ()

其他资源

有关 Athena 中性能调整的其他信息,请考虑以下资源: