如何编写子查询来优化性能?



我有以下查询,显示所选维度的总销售额。Table a不包含product_name,这就是为什么我在product_id上与table b连接数据的原因。

然而,table b太大了,我想优化它来扫描更少的数据。

SELECT a.date,
a.hour,
a.category_id,
a.product_id,
b.product_name,  
sum(a.sales) AS sales
FROM  a
LEFT JOIN b
ON a.product_id = b.product_id
WHERE date(a.date) >= date('2021-01-01') 
AND date(B.date) = date('2021-01-01')
GROUP BY  1, 2, 3, 4, 5
你有什么建议吗?

有两种方法可以减少Athena需要为给定查询扫描的数据量:

  1. 确保表是分区的,并且确保查询使用了分区。
  2. 将数据存储为Parquet或ORC。

这两者可以单独使用,也可以组合使用。最好的结果是通过组合,但有时不方便或不可能。

你的问题没有说表是否分区,但从查询来看,我觉得它们不是-除非date是分区键。

date将是一个很好的分区键,如果是,那么您的查询已经很好了。AND date(B.date) = date('2021-01-01')将把对表b的扫描限制在一个分区内。但是,如果date不是分区键,那么Athena将不得不扫描整个表以找到符合条件的行。

这就是像Parquet和ORC这样的文件格式可以提供帮助的地方;它们分别存储每个列的数据,还存储每个列的min和Max值等元数据。如果b表的文件是按date排序的,或者至少是按date排序的方式创建的,那么Athena将能够查看元数据并跳过不能包含查找日期的文件,因为它超出了该文件的最小/最大值给出的范围。Athena也只需要读取b表中包含date列的部分文件,因为这是查询中唯一使用的一个。

如果你用更多关于表模式和数据如何存储的信息来修改你的问题,我可以更详细地回答如何优化。根据现有的信息,我只能给出上述的一般指导。

  1. 确保b表在日期和product_id上有索引,正如Stu的评论所建议的
  2. 在SQL上运行一个解释计划(从控制台),看看优化器是否在加入到a之前过滤了b。如果它已经这样做了,你就完成了-步骤3不会有帮助
  3. From a Left Join b替换为From a Left Join (Select product_id, product_name from b where date(date) = date('2021-01-01')) b

最新更新