我的数据集是1,000,000行,约390,000列。这些字段都是二进制的,0或1.数据非常稀疏。
我一直在使用Spark来处理这些数据。我目前的任务是过滤数据 - 我只想要预先选择的1000列数据。这是我用来完成此任务的当前代码:
val result = bigdata.map(_.zipWithIndex.filter{case (value, index) => selectedColumns.contains(index)})
bigdata
只是RDD[Array[Int]]
但是,此代码需要相当长的时间才能运行。我确信这是一种更有效的方法来过滤我的数据集,而这些数据集并不涉及分别进入和过滤每一行。是否会将我的数据加载到DataFrame中,并通过DataFrame API对其进行操作,从而使事情变得更快/更容易?我应该查看基于列存储的数据库吗?
答案 0 :(得分:2)
您可以从提高过滤效率开始。请注意:
RDD
包含Array[Int]
。这意味着您可以在 O(1)时间考虑到这两个事实,显而易见的是迭代每一行的所有元素而不提contains
次调用是没有意义的。相反,您只需map
而不是selectedColumns
// Optional if selectedColumns are not ordered
val orderedSelectedColumns = selectedColumns.toList.sorted.toArray
rdd.map(row => selectedColumns.map(row))
比较时间复杂度:
zipWithIndex
+ filter
(假设contains
O(1)时最佳情况) - O(#rows *#columns) map
- O(#rows * #selectedColumns) 答案 1 :(得分:1)
加速执行的最简单方法是将其与partitionBy并行化:
row_number()
foreachPartition会收到一个迭代器,您可以在其上进行映射和过滤。
numPartitions是一个val,您可以使用所需的并行分区数量来设置。