我正在基于PrestoDB的AWS Athena上运行此程序。我最初的计划是查询过去3个月的数据来分析这些数据。然而,即使是过去2小时的查询时间也需要超过30分钟,此时query超时。有没有更有效的方法来执行查询?
SELECT column1, dt, column 2
FROM database1
WHERE date_parse(dt, '%Y%m%d%H%i%s') > CAST(now() - interval '1' hour AS timestamp)
日期列以字符串YYYYMmdhhmmss 的形式记录
问题可能是查询对要筛选的列应用了函数。这是低效的,因为数据库需要转换整个列才能过滤它。有人说这个谓词是非SARGable。
您的主要工作应该是修复数据模型,并将日期存储为date
s,而不是字符串。
也就是说,您用来表示日期的字符串格式仍然可以使用直接筛选。其想法是将筛选值转换为目标字符串格式(而不是将列值转换为日期(:
where dt > date_format(now() - interval '1' hour, '%Y%m%d%H%i%s')
有很多不同的因素会影响Athena执行查询所需的时间。数据量通常占主导地位,但其他重要因素是数据格式(例如CSV和Parquet之间存在巨大差异(和文件数量。与许多其他新的数据库情况相比,查询的复杂性通常不是一个重要因素,您的查询非常简单,也不是问题所在(在WHERE
条件的两侧都应用一个函数没有帮助,但在Athena中这并不是什么大不了的,因为过滤是暴力的,与像Athena这样的引擎中的IO相比,在每行应用一个功能也没什么大不了。
如果您提供更多关于文件数量、数据格式等的信息,我们可能会更好地帮助您,因为如果没有这些信息,可能什么都没有。我的怀疑是,你有一个类似于带有数千万或数亿个文件的单个前缀的东西——这对雅典娜来说是最糟糕的情况。
当Athena计划查询时,它会在S3上列出表的位置。S3的列表操作的页面大小为1000,因此如果文件数量超过这个数量,Athena将不得不按顺序列出,直到获得完整的列表。这是不可能平行的,而且速度也不是很快。
几乎不惜一切代价,您需要避免在同一前缀中有超过1000个文件。如果你有更多的文件,你可以添加前缀(目录(,因为Athena会把S3列为一个文件系统,并并行列出前缀。table-data/a/
、table-data/b/
、table-data/c/
中的1000个文件比table-data/
中的3000个文件要好得多。
我之所以怀疑它是很多小文件,而不是很多数据,是因为如果它是很多数据,你可能会这么说——而很多数据实际上是雅典娜真正擅长的。除非是十亿个小文件,否则篡改万亿字节的数据是没有问题的。