【问题标题】:Subquery in partitioned Athena tables分区 Athena 表中的子查询
【发布时间】:2020-10-16 10:15:18
【问题描述】:

我在 Athena 中使用分区。我有一个名为快照的分区,当我这样调用查询时:

select * from mytable where snapshot = '2020-06-25'

然后,正如预期的那样,只扫描指定的分区并且我的查询很快。但是,如果我使用返回单个日期的子查询,那就太慢了:

select * from mytable where snapshot = (select '2020-06-25')

上面实际上是扫描所有分区而不仅仅是指定日期,导致性能非常低。

我的问题是我可以使用子查询来指定分区并提高性能。我需要使用子查询来添加一些自定义逻辑,该逻辑根据某些条件返回日期。

【问题讨论】:

  • 显然不是。如果该子查询不起作用,那么很难想象有一个会起作用。我认为这个想法是运行子查询,但结果是某种变量并使用它来生成 SQL。
  • 您可以使用 Athena API(如 Python 的 boto3)从自定义逻辑中查询和获取日期,并在后续查询调用中使用。
  • 请检查where snapshot IN (select '2020-06-25') 是否同样有效 - 全面扫描?
  • @leftjoin 是的,IN 和 = 具有相同的效果。
  • @VamsiPrabhala 谢谢,是的,这是我目前倾向于的解决方案,除非我可以选择在 sql 中完成所有操作。

标签: sql hive presto amazon-athena trino


【解决方案1】:

编辑:

Trino 356 能够内联此类查询,请参阅https://github.com/trinodb/trino/issues/4231#issuecomment-845733371

旧答案:

Presto 仍然不会像 (select '2020-06-25') 那样内联琐碎的子查询。 这由https://github.com/trinodb/trino/issues/4231 跟踪。 因此,您不应期望 Athena 内联,因为它基于 Presto .172。

我需要使用子查询来添加一些自定义逻辑,该逻辑根据某些条件返回日期。

如果您的查询要更复杂,而不是常量表达式,则无论如何都不会内联。如果snapshot 是分区键,那么您可以利用最近添加的功能——动态分区修剪。在https://trino.io/blog/2020/06/14/dynamic-partition-pruning.html 阅读更多信息。 这当然假设您可以选择 Presto 版本。

如果您受限于 Athena,您唯一的选择是在主查询之外(单独)评估子查询,并将其作为常量(例如文字)传递回主查询。

【讨论】:

    【解决方案2】:

    2020 年末发布的 Athena 2.0 似乎改进了它们的 push_down_predicate 处理以支持子查询。

    这是他们来自https://docs.aws.amazon.com/athena/latest/ug/engine-versions-reference.html#engine-versions-reference-0002的相关声明

    谓词推理和下推——为使用 IN 谓词的查询扩展了谓词推理和下推。

    我对我们自己的 Athena 表的测试表明情况确实如此。我的测试查询大致如下

    SELECT *
    FROM table_partitioned_by_scrape_date
    WHERE scrape_date = (
      SELECT max(scrape_date) 
      FROM table_partitioned_by_scrape_date
    )
    

    从查询扫描到的字节,我可以告诉雅典娜确实只扫描了最新的scrape_date的分区。

    此外,我还在 JOIN 子句中测试了对 push_down_predicate 的支持,其中 join_to 值是另一个查询的结果。即使在发行说明中没有提到,显然 Athena 2.0 现在也足够聪明,可以支持这种情况,并且只扫描最新的 scrape_date 分区。我之前在 Athena 1.0 中测试过类似的查询,它会扫描所有分区。我的测试查询如下

    WITH l as (
      SELECT max(scrape_date) as latest_scrape_date
      FROM table_partitioned_by_scrape_date
    )
    SELECT deckard_id
    FROM table_partitioned_by_scrape_date as t
    JOIN l ON t.scrape_date = l.latest_scrape_date
    

    【讨论】:

      猜你喜欢
      • 2019-09-16
      • 2021-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-08
      • 1970-01-01
      • 2021-04-29
      • 2021-10-09
      相关资源
      最近更新 更多