如何使用Spark

时间:2019-05-27 13:27:20

标签: sql apache-spark apache-spark-sql hiveql

我拥有几乎每天都添加数据的数据集,并且每天都需要在较大的ETL的一部分中进行处理。 当我直接选择分区时,查询速度很快:

SELECT * FROM JSON.`s3://datalake/partitoned_table/?partition=2019-05-20`

但是,问题在于该事件类型在某些星期日不生成数据,从而导致该特定日期的分区不存在。因此,我无法使用上一条语句来执行日常工作。

另一种尝试使我尝试使Spark查找该数据集的最新分区,以确保更大的查询不会失败:

SELECT * FROM JSON.`s3://datalake/partitoned_table/`
WHERE partition = (SELECT MAX(partition) FROM JSON.`s3://datalake/partitoned_table/`)

这每次都有效,但是它的速度令人难以置信。

我找到了许多有关如何构建和维护分区的文章和参考,但对于如何正确读取分区却一无所知。

您知道如何正确完成此操作吗?

2 个答案:

答案 0 :(得分:2)

(SELECT MAX(partition) FROM JSON.s3://datalake/partitoned_table/)
该查询将作为Spark中的子查询执行。
速度慢的原因
1.子查询需要在实际查询开始执行之前完全执行。
2.上述查询将列出所有S3文件以检索分区信息。如果文件夹中包含大量文件,则此过程将花费很长时间。列出时间与文件数量成正比。

我们可以使用分区方案在s3://datalake/partitoned_table/上创建一个表,假设该表的名称为tbl
您可以执行
ALTER TABLE tbl RECOVER PARTITIONS
将分区信息存储在metastore中。这也涉及到列表,但这是一次操作,并且spark会生成多个线程来执行列表以使其更快。

那我们可以开枪

SELECT * FROM tbl WHERE partition = (SELECT MAX(partition) FROM tbl`)

仅从metastore中获得分区信息,而不必列出我认为这是昂贵操作的对象存储。
这种方法的成本是恢复分区的成本。
之后,所有查询都会更快(当新分区的数据到来时,我们需要再次恢复分区)

答案 1 :(得分:1)

没有Hive时进行WorkAround-

FileSystem.get(URI.create("s3://datalake/partitoned_table"), conf).listStatus(new Path("s3://datalake/partitoned_table/"))

以上代码将为您提供文件分区列表example - List(s3://datalake/partitoned_table/partition=2019-05-20, s3://datalake/partitoned_table/partition=2019-05-21....)

这非常有效,因为它仅从s3位置获取元数据。

只需获取最新的文件分区,然后将其用于SQL。