高效的计数与Apache Spark不同

时间:2014-06-19 16:50:05

标签: distinct apache-spark

有1亿客户在几个网站的页面上点击1000亿次(假设有100个网站)。点击流可在大型数据集中使用。

使用Apache Spark的抽象,每个网站计算不同访问者的最有效方法是什么?

8 个答案:

答案 0 :(得分:39)

visitors.distinct().count()将是显而易见的方式,第一种方式是明确的,您可以指定并行度,也可以看到速度的提高。如果可以将访问者设置为流并使用D流,则可以实时计算。您可以直接从目录流式传输,并使用与RDD相同的方法,如:

val file = ssc.textFileStream("...") file.distinct().count()

最后一个选项是使用def countApproxDistinct(relativeSD: Double = 0.05): Long但是这被标记为实验性的,但如果relativeSD(标准偏差)更高,则会明显快于计数。

编辑:由于您希望每个网站的计数只能减少网站ID,因此可以有效地完成(使用合并器),因为计数是聚合的。如果您有一个RDD的网站名称用户ID元组,您可以这样做。 visitors.countDistinctByKey()visitors.countApproxDistinctByKey(),大约一个是实验性的。要使用大约不同的键,您需要PairRDD

有趣的附注如果你对近似值没问题并希望得到快速结果,你可能需要研究由与火花放大器实验室相同的人制作的blinkDB

答案 1 :(得分:10)

我必须做类似的事情,你可以做的一件有效的事情(那不是真正的火花)是将你的游客ID映射到字节列表而不是GUID字符串,你可以节省4倍的空间(作为2个字符)是单字节的十六进制编码,字符串中的Char使用2个字节。

// Inventing these custom types purely for this question - don't do this in real life!
type VistorID = List[Byte]
type WebsiteID = Int

val visitors: RDD[(WebsiteID, VisitorID)] = ???

visitors.distinct().mapValues(_ => 1).reduceByKey(_ + _)

请注意,您也可以这样做:

visitors.distinct().map(_._1).countByValue()

但这也不会扩展。

答案 2 :(得分:9)

我注意到,在RDD上运行它时,基本的不同功能可以比在DataFrame集合上运行它快得多。例如:

DataFrame df = sqlContext.load(...)
df.distinct.count // 0.8 s
df.rdd.distinct.count // 0.2 s

答案 3 :(得分:8)

如果dataRDD(网站,访问者)对,则data.countApproxDistinctByKey(0.05)将为您提供RDD(网站,计数)。可以减少参数以获得更高的准确性,但代价是更多的处理。

答案 4 :(得分:6)

答案 5 :(得分:4)

如果您想要每个网页,那么visitors.distinct()...效率低下。如果有很多访问者和大量网页,那么您就可以区分大量的(webpage, visitor)组合,这可能会压倒内存。

这是另一种方式:

visitors.groupByKey().map { 
  case (webpage, visitor_iterable)
  => (webpage, visitor_iterable.toArray.distinct.length)
}

这要求单个网页的访问者适合内存,因此在所有情况下可能都不是最好的。

答案 6 :(得分:3)

Sim给了a great discussion about the count distinct problem at the Spark Summit in Europe

HyperLogLog algo最适合需要逐步更新的大量不同计算。

Tagar链接到的ApproxCountDistinct算法并不是最好的算法,因为它们不公开底层的HLL草图且无法重新汇总(Sim在他的演讲中对此进行了讨论)。

This blog post介绍了如何使用spark-alchemy库创建可重新聚合的HLL草图。好玩的东西!

答案 7 :(得分:0)

Df.select(approx_count_distinct("col_name",0.1))

0.1是表示允许的最大估计误差的参数。 使用大数据集,您会看到很多出色的性能。