最近,当分区数量很多时,我遇到了AWS Athena的问题。
旧版本的数据库和表只有1个分区级别,例如id = x。我们来一张桌子。例如,我们在每个ID(产品)存储付款参数的地方,并且没有足够的ID。假设其在1000-5000附近。现在,在查询带有where子句的id号的表时,例如“ .. where id = 10”。实际上,查询返回的速度非常快。假设我们每天两次更新数据。
最近,我们一直在考虑为一天添加另一个分区级别,例如“ ../id=x/dt=yyyy-mm-dd/ ..”。这意味着,如果一个月过去,并且每天有3000个ID,则分区号每天会增加xID倍,我们每个月大约可获得3000x30 = 90000个分区。因此,分区数量迅速增长。
假设有3个月大的数据(约27万个分区),我们希望看到类似以下查询的查询最多在20秒左右的时间内返回。
select count(*) from db.table where id = x and dt = 'yyyy-mm-dd'
这大约需要一分钟。
真实案例
事实证明,Athena首先获取所有分区(元数据)和s3路径(无论where子句的使用情况),然后过滤您希望在where条件下看到的那些s3路径。第一部分(按分区获取所有s3路径的时间与分区数成正比)
您拥有的分区越多,查询执行的速度就越慢。
凭直觉,我希望雅典娜只能获取在where子句中声明的s3路径,这意味着这是分区的一种神奇方法。也许获取所有路径
编辑
为了阐明上述说法,我在支持邮件中添加了一部分。
来自支持
...您提到您的新系统有360000个庞大的数字。因此,在执行操作时
select * from <partitioned table>
,Athena首先下载所有分区元数据,并搜索与这些分区映射的S3路径。为每个分区获取数据的过程会导致查询执行时间更长。...
更新资料
在AWS论坛上打开了一个问题。在aws论坛上提出的链接问题在这里。
谢谢。
如果不知道数据量,什么文件格式以及我们在谈论多少个文件,就不可能正确回答。
TL; DR,我怀疑您的分区包含成千上万个文件,并且瓶颈正在列出并全部读取。
对于随时间增长的任何数据集,您都应该根据查询模式对日期甚至时间进行时间分区。如果您应该在其他属性上进行分区取决于很多因素,最后通常会发现,最好不要分区。并非总是如此,但经常如此。
在许多情况下,使用合理大小(〜100 MB)的Parquet可能比分区更有效。原因是分区增加了必须在S3上列出的前缀数量,以及必须读取的文件数量。在许多情况下,单个100 MB的Parquet文件可能比十个10 MB的文件效率更高。
雅典娜执行查询时,它将首先从Glue加载分区。Glue支持对分区进行有限的筛选,并且将在修剪分区列表方面有所帮助–因此,据我所知,Athena读取所有分区元数据并不是事实。
当具有分区时,它将LIST
对分区位置执行操作以收集查询中涉及的文件–换句话说,Athena不会列出每个分区位置,仅列出为查询选择的分区中的文件。这可能仍然很大,这些列表操作绝对是瓶颈。如果一个分区中有超过1000个文件,这将变得特别糟糕,因为这是S3列表操作的页面大小,并且必须顺序执行多个请求。
在列出所有文件的情况下,Athena会生成一个拆分列表,该拆分列表可能等于也可能不等于文件列表–某些文件格式是可拆分的,并且如果文件足够大,则会拆分并并行处理。
只有完成所有这些工作之后,实际查询处理才开始。根据拆分的总数和Athena群集中的可用容量的数量,将为您的查询分配资源并开始执行。
如果您的数据是Parquet格式,并且每个分区有一个或几个文件,那么问题中的count查询应该在一秒钟或更短的时间内运行。Parquet的文件中有足够的元数据,因此计数查询不必读取数据,而只需读取文件页脚即可。由于涉及多个步骤,因此很难在不到一秒钟的时间内运行任何查询,但是命中单个分区的查询应该可以快速运行。
因为要花两分钟,所以我怀疑每个分区中有数百个文件(如果不是数千个),并且您的瓶颈是运行所有列表并在S3中进行操作需要太多时间。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句