避免在Apache Spark中使用Java数据结构以避免复制数据

时间:2016-06-02 08:28:54

标签: apache-spark apache-spark-sql spark-dataframe

我有一个MySQL数据库,其中一个表包含大约1亿条记录(~25GB,~5列)。使用Apache Spark,我通过JDBC连接器提取此数据并将其存储在DataFrame中。 从这里开始,我会对数据进行一些预处理(例如替换NULL值),所以我绝对需要遍历每条记录。 然后我想执行降维和特征选择(例如使用PCA),执行聚类(例如K-Means),然后在新数据上进行模型测试。

我已经在Spark的Java API中实现了这个,但它太慢了(为了我的目的),因为我做了大量的数据从DataFrame复制到java.util.Vector和java.util.List(到能够迭代所有记录并进行预处理),然后回到DataFrame(因为Spark中的PCA需要一个DataFrame作为输入)。

我尝试将数据库中的信息提取到org.apache.spark.sql.Column中,但无法找到迭代它的方法。 我还试图通过使用org.apache.spark.mllib.linalg。{DenseVector,SparseVector}来避免使用Java数据结构(例如List和Vector),但是也无法使用它。 最后,我还考虑使用JavaRDD(通过从DataFrame和自定义模式创建它),但无法完全解决它。

经过冗长的描述,我的问题是:有没有办法完成第一段中提到的所有步骤,而不将所有数据复制到Java数据结构中? 也许我试过的其中一个选项实际上可以工作,但我似乎无法弄清楚如何,因为关于Spark的文档和文献有点稀缺。

1 个答案:

答案 0 :(得分:0)

从问题的措辞来看,似乎对Spark处理的各个阶段存在一些困惑。

首先,我们通过指定输入和转换告诉Spark要做什么。此时,唯一已知的事情是(a)处理的各个阶段的分区数量和(b)数据的模式。在此阶段使用org.apache.spark.sql.Column来标识与列关联的元数据。但是,它不包含任何数据。事实上,现阶段根本没有数据。

其次,我们告诉Spark对数据框/数据集执行操作。这就是启动处理的原因。读取输入并流入各种转换并进入最终操作操作,无论是collect还是save还是其他操作。

因此,这就解释了为什么你不能“将数据库中的信息提取到”Column

至于你问题的核心,如果没有看到你的代码并且确切知道你想要完成什么,就很难评论,但可以肯定的是,在类型之间进行大量迁移是一个坏主意。

以下几个问题可能有助于指导您获得更好的结果:

  • 为什么不能直接在Row个实例上执行所需的数据转换?

  • 将部分转换代码包装到UDF或UDAF中是否方便?

希望这有帮助。