我正在使用Spark GraphFrames使用大量(?)图(?)图(?)图(6000万个顶点和95亿个边缘)。基础数据并不大 - 顶点在磁盘上大约需要500MB,边缘约为40GB。我的容器经常由于爪哇堆的内存问题而关闭,但我认为根本的问题是GraphFrame不断地在周围进行整理数据(我看到Shuffle读/写下最多150GB)。有没有办法有效地分区图形框架或基础边缘/顶点来减少洗牌?
tl; dr 不可能有效地分区Graphframe
。
Graphframe
算法可以分为两类:
-
将处理委派给
GraphX
的方法。GraphX支持多种分区方法,但这些方法不是通过Graphframe
API暴露的。如果使用其中一种,则最好直接使用GraphX
。不幸的是,
GraphX
的开发几乎完全停止,在过去的两年中,几乎只有一些小修复程序,而且与核心库和核心库相比,总体表现非常令人失望。 -
使用SPARK
Datasets
在本地实施的方法,该方法考虑有限的编程模型和仅单个分区模式,非常不适合复杂的图形处理。虽然可以将关系柱存储用于有效的图形处理,而
>Graphframes
采用的幼稚迭代join
方法只是不扩展(但要用一个或两个啤酒花进行浅横扫是可以的)。'您可以尝试分别由
id
和src
重新分配vertices
和edges
DataFrames
:val nPart: Int = ??? GraphFrame(v.repartition(nPart, v("id")), e.repartition(e(nPart, "src")))
在某些情况下应该有所帮助。
总体而言,以当前(2016年12月)状态,Spark不是密集图分析的好选择。
这是部分解决方案/解决方案 - 创建一个UDF,该UDF模拟该分区功能之一以创建一个新列和分区。
num_parts = 256
random_vertex_cut = udf.register("random_vertex_cut", lambda src, dst: math.abs((src, dst).hashCode()) % num_parts, IntegerType())
edge.withColumn("v_cut", random_vertex_cut(col("src"), col("dst")).repartition(256, "v_cut")
这种方法可以帮助某些,但不能像GraphX一样。