Spark:如何在没有内存的情况下收集大量数据

时间:2018-05-08 00:46:02

标签: apache-spark dataframe sparkr

我有以下问题:

我在HDFS上的一组镶木地板文件上进行sql查询,然后我进行收集以获得结果。

问题是当有很多行时我会出现内存不足错误。

此查询需要随机播放,因此我无法对每个文件执行查询。

一种解决方案可能是迭代列的值并将结果保存在磁盘上:

df = sql('original query goes here')
// data = collect(df) <- out of memory
createOrReplaceTempView(df, 't')
for each c in cities
    x = collect(sql("select * from t where city = c")
    append x to file

据我所知,这将导致程序花费太多时间,因为将对每个城市执行查询。

这样做的最佳方式是什么?

3 个答案:

答案 0 :(得分:1)

正如@ cricket_007所说,我不会collect()来自Spark的数据将其附加到R中的文件中。  此外,迭代SparkR::distinct()城市列表然后从这些表中选择所有内容以将它们附加到某些输出数据集是没有意义的。您唯一想要这样做的是,如果您尝试基于某种条件逻辑在每个组中执行另一个操作,或者使用SparkR中不可用的函数对每个组应用操作。

我认为你试图获得一个数据框(Spark或R),其中观察结果以某种方式分组,这样当你看到它们时,一切都很美。为此,请在第一个SQL查询中添加GROUP BY city子句。从那里,只需将数据写回HDFS或其他输出目录。根据我对你的问题的理解,也许做这样的事情会有所帮助:

sdf <- SparkR::sql('SELECT SOME GREAT QUERY FROM TABLE GROUP BY city')

SparkR::write.parquet(sdf, path="path/to/desired/output/location", mode="append")

这会在一个文件中提供您的所有数据,并且应该按city进行分组,这是我认为您在问题中尝试使用第二个查询。

您可以通过以下方式确认输出:

newsdf<- SparkR::read.parquet(x="path/to/first/output/location/")
View(head(sdf, num=200))
祝你好运,希望这会有所帮助。

答案 1 :(得分:0)

如果内存耗尽,这意味着输出数据真的很大,所以, 您可以将结果写入某个文件本身,就像镶木地板文件一样。

如果您想进一步执行某些操作,可以在此收集的数据上读取此文件中的数据。

对于大型数据集,我们不应使用collect(),而是可以使用take(100)take(some_integer)来检查某些值是否正确。

答案 2 :(得分:0)

由于您的数据很大,因此不再可能使用 collect() 了。因此,您可以使用策略对数据进行采样并从采样数据中学习。

import numpy as np
arr = np.array(sdf.select("col_name").sample(False, 0.5, seed=42).collect())

在这里,您对 50% 的数据和仅一列进行采样。