sql - 使用聚合函数时减少 Athena 扫描的数据量

标签 sql presto amazon-athena trino

下面的查询扫描 100 mb 的数据。

select * from table where column1 = 'val' and partition_id = '20190309';

然而,下面的查询扫描了 15 GB 的数据(有超过 90 个分区)
select * from table where column1 = 'val' and partition_id in (select max(partition_id) from table);

如何优化第二个查询以扫描与第一个相同数量的数据?

最佳答案

这里有两个问题。 select max(partition_id) from table 上面标量子查询的效率,以及@PiotrFindeisen 指出的关于动态过滤的效率。
第一个问题是对 Hive 表的分区键的查询比它们看起来复杂得多。大多数人会认为,如果您想要分区键的最大值,您可以简单地对分区键执行查询,但这不起作用,因为 Hive 允许分区为空(并且它还允许非空文件不包含行)。具体来说,select max(partition_id) from table 上面的标量子查询需要 Trino (formerly PrestoSQL) 找到至少包含一行的最大分区。理想的解决方案是在 Hive 中拥有完美的统计数据,但除此之外,引擎需要为 Hive 提供自定义逻辑,以打开分区的文件,直到找到非空的文件为止。
如果您确定您的仓库不包含空分区(或者如果您同意其含义),您可以用隐藏的 $partitions 表上的一个替换标量子查询“

select * 
from table 
where column1 = 'val' and 
    partition_id = (select max(partition_id) from "table$partitions");
第二个问题是@PiotrFindeisen 指出的,它与查询的计划和执行方式有关。大多数人会看上面的查询,发现引擎显然应该在计划期间计算 select max(partition_id) from "table$partitions" 的值,将其内联到计划中,然后继续优化。不幸的是,这是一个非常复杂的通用决定,因此引擎只是简单地将其建模为广播连接,其中执行的一部分计算出该值,并将该值广播给其他工作人员。问题是执行的其余部分无法将这些新信息添加到现有处理中,因此它只是扫描所有数据,然后过滤掉您试图跳过的值。有一个项目正在进行中以添加此 dynamic filtering ,但尚未完成。
这意味着您今天可以做的最好的事情是运行两个单独的查询:一个获取最大 partition_id,另一个获取内联值。
顺便说一句,隐藏的“$partitions”表是在 Presto 0.199 中添加的,我们修复了 0.201 中的一些小错误。我不确定 Athena 基于哪个版本,但我相信它已经过时了(我写这个答案时的当前版本是 309

关于sql - 使用聚合函数时减少 Athena 扫描的数据量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55873006/

相关文章:

mysql - SQL:从 Month_year 名称列中获取月份的开始日期

mysql - 如何将某些列数据从第一个表移动到第二个表。并在单个查询中用不同的数据填充第二个表的其他列

Mysql "like"返回意外结果

sql - Athena/SQL 查询以获得所需结果

amazon-web-services - 使用 jdbc url 限制对特定 Amazon Athena 数据库的查询

mysql - 我在哪里可以阅读有关 MySQL 查询的时间复杂度(Big-O 表示法)的信息?

amazon-web-services - Amazon Athena View 实际上是 hive View ,还是单独的附加 View ?

json - 如何在 Presto 中交叉连接取消嵌套 JSON 数组

hadoop - 关于 Hadoop 和 Hive 和 Presto 的问题

sql - 在aws athena中计算百分位数