2016-07-05 32 views
0

我正在使用强大的Z-Score方法来查找使用Spark SQL的许多列中的异常。不幸的是,这涉及到计算许多中位数,不幸的是效率很低。我做了一些搜索,但找不到任何内置的高效库来进行近似或快速的中值计算。在许多元素上高效地找到中值或近似中值

每次运行我的查询,其涉及下面的 “sqlContext.sql(” 选择percentile_approx( “+ colname的+”,0.5)FROM分配 “)”,我最终接收以下错误:

Name: java.lang.OutOfMemoryError 
Message: GC overhead limit exceeded 

所以我假设这种方法在实践中绝对不是太可用。 如果有必要,我可以发布我的代码的一部分(我还没有,因为它现在有点复杂,但如果需要,我可以)。我的数据集最多只有500k点,所以你们认为这是一个缓存效率低下的问题,还是我的数据使用问题,还是我需要更好的方法来找到中值?

+0

为什么不只是对元素进行排序并取大小/第2个元素?这是更快更容易 – GameOfThrows

+0

@GameOfThrows有没有一个好的方法来做到这一点,而不必定义一个新的DataFrame?目前我对Spark比较陌生。 –

+0

如果是这样,它从未成为Spark的一部分。这只是一个Hive代码,恰好与Spark兼容。 – zero323

回答

0

如果你想使用蜂巢UDF如你问题,你可以提供确定使用了多项纪录附加参数:

import org.apache.spark.mllib.random.RandomRDDs 

RandomRDDs.normalRDD(sc, 100000).map(Tuple1(_)).toDF("x").registerTempTable("df") 

sqlContext.sql("SELECT percentile_approx(x, 0.5, 100) FROM df").show() 

// +--------------------+ 
// |     _c0| 
// +--------------------+ 
// |-0.02626781447291...| 
// +--------------------+ 

sqlContext.sql("SELECT percentile_approx(x, 0.5, 10) FROM df").show() 

// +-------------------+ 
// |    _c0| 
// +-------------------+ 
// |-0.4185534605295841| 
// +-------------------+ 

的默认值是10000因此,尽管它仍然是昂贵的,因为相关在实践中洗牌应该不会导致OOM。它表明,你的配置或查询可能还有其他一些问题超出了中值计算本身。

请注意,Spark 2.0.0提供了原生百分比近似方法,如How to find median using Spark中所述。