背景

简单分析一下GraphX是怎么为图数据建模和存储的。

入口

能够看GraphLoader的函数。

def edgeListFile(
sc: SparkContext,
path: String,
canonicalOrientation: Boolean = false,
numEdgePartitions: Int = -1,
edgeStorageLevel: StorageLevel = StorageLevel.MEMORY_ONLY,
vertexStorageLevel: StorageLevel = StorageLevel.MEMORY_ONLY)
: Graph[Int, Int]
  1. path能够是本地路径(文件或目录),也能够是hdfs路径,本质上是使用sc.textFile来生成HadoopRDD的,numEdgePartitions是分区数。
  2. Graph的存储是分EdgeRDD和VertexRDD两块,能够分别设置StorageLevel。默认是内存。
  3. 这个函数接受边文件。即’1 2’, ‘4 1’这种点到点的数据对组成的文件。

    把这份文件按分区数和存储level转化成一个能够操作的图。

流程

  1. sc.textFile读文件。生成原始的RDD
  2. 每一个分区(的计算节点)把每条记录放进PrimitiveVector里,这个结构是spark里为primitive数据优化的存储结构。

  3. 把PrimitiveVector里的数据一条条取出。转化成EdgePartition,即EdgeRDD的分区实现。这个过程中生成了面向列存的结构:src点的array,dst点的array。edge的属性array,以及两个正反向map(用于相应点的local id和global id)。

  4. 对EdgeRDD 做一次count触发这次边建模任务,真正persist起来。

  5. 用EdgePartition去生成一个RoutingTablePartition,里面是vertexId到partitionId的相应关系。借助RoutingTablePartition生成VertexRDD。

  6. 由EdgeRDD和VertexRDD生成Graph。前者维护了边的属性、边两头顶点的属性、两头顶点各自的global vertexID、两头顶点各自的local Id(在一个edge分区里的array index)、用于寻址array的正反向map。

    后者维护了点存在于哪个边的分区上的Map。

下面是代码,比較清晰地展现了内部存储结构。

private[graphx]
class EdgePartition[
@specialized(Char, Int, Boolean, Byte, Long, Float, Double) ED: ClassTag, VD: ClassTag](
localSrcIds: Array[Int],
localDstIds: Array[Int],
data: Array[ED],
index: GraphXPrimitiveKeyOpenHashMap[VertexId, Int],
global2local: GraphXPrimitiveKeyOpenHashMap[VertexId, Int],
local2global: Array[VertexId],
vertexAttrs: Array[VD],
activeSet: Option[VertexSet])
extends Serializable {
/**
* Stores the locations of edge-partition join sites for each vertex attribute in a particular
* vertex partition. This provides routing information for shipping vertex attributes to edge
* partitions.
*/
private[graphx]
class RoutingTablePartition(
private val routingTable: Array[(Array[VertexId], BitSet, BitSet)]) extends Serializable {

细节

分区摆放

EdgeRDD的分区怎么切分的呢?由于数据是依据HadoopRDD从文件中依据offset扫出来的。能够理解为对边数据的切分是没有不论什么处理的。由于文件也没有特殊排列过,所以切分成多少个分区应该就是随机的。

VertexRDD的分区怎么切分的呢?EdgeRDD生成的vertexIdToPartitionId这份RDD数据是RDD[VertexId, Int]型,它依据hash分区规则,分成和EdgeRDD分区数一样大。

所以VertexRDD的分区数和Edge一样。分区规则是Long取hash。

所以我能够想象的计算过程是:

对点操作的时候,首先对vertexId(是个Long)进行hash,找到相应分区的位置,在这个分区上,假设是内存存储的VertexRDD,那非常快能够查到它的边所在的几个Edge分区的所在位置,然后把计算分到这几个Edge所在的分区上去计算。

第一步依据点hash后找边分区位置的过程就相似一次建好索引的查询。

配官方图方面理解:

高效数据结构

对原生类型的存储和读写有比較好的数据结构支持,典型的是EdgePartition里使用的map:

/**
* A fast hash map implementation for primitive, non-null keys. This hash map supports
* insertions and updates, but not deletions. This map is about an order of magnitude
* faster than java.util.HashMap, while using much less space overhead.
*
* Under the hood, it uses our OpenHashSet implementation.
*/
private[graphx]
class GraphXPrimitiveKeyOpenHashMap[@specialized(Long, Int) K: ClassTag,
@specialized(Long, Int, Double) V: ClassTag](

以及之前提到的vector

/**
* An append-only, non-threadsafe, array-backed vector that is optimized for primitive types.
*/
private[spark]
class PrimitiveVector[@specialized(Long, Int, Double) V: ClassTag](initialSize: Int = 64) {
private var _numElements = 0
private var _array: Array[V] = _

全文完 :)

GraphX 图数据建模和存储的更多相关文章

  1. 【mysql的设计与优化专题(1)】ER图,数据建模与数据字典

    需求分析是做项目中的极为重要的一环,而作为整个项目中的'血液'--数据,更是重中之重.viso,workbench,phpmyadmin等软件可以帮我们更好的处理数据分析问题. ER图 E-R方法是& ...

  2. 《Entity Framework 6 Recipes》翻译系列 (3) -----第二章 实体数据建模基础之创建一个简单的模型

    第二章 实体数据建模基础 很有可能,你才开始探索实体框架,你可能会问“我们怎么开始?”,如果你真是这样的话,那么本章就是一个很好的开始.如果不是,你已经建模,并在实体分裂和继承方面感觉良好,那么你可以 ...

  3. 《驾驭Core Data》 第三章 数据建模

    本文由海水的味道编译整理,请勿转载,请勿用于商业用途.    当前版本号:0.1.2 第三章数据建模 Core Data栈配置好之后,接下来的工作就是设计对象图,在Core Data框架中,对象图被表 ...

  4. NoSQL 数据建模技术(转)

    本文转载自:http://coolshell.cn/articles/7270.html ================================================ 全文译自墙外 ...

  5. NoSQL数据建模技术

    原文来自“NoSQL Data Modeling Techniques”,由酷壳网陈皓编译<NoSQL数据建模技术>.这篇文章看完之后,你可能会对NoSQL的数据结构会有些感觉.我的感觉是 ...

  6. kityminder-editor + MongoDB 思维导图数据自动实时保存方案

    最近开始做自己的第一个开源项目:一个基于思维导图的测试用例管理系统MinderCase,在做了一周的技术调研后,决定采用kityminder-editor作为思维导图编辑器,为了支持实时存储,当思维导 ...

  7. Cassandra数据建模中最重要的事情:主键

    Cassandra数据建模中要了解的最重要的事情:主键 使用关系数据建模,您可以从主键开始,但是RDBMS中的有效数据模型更多地是关于表之间的外键关系和关系约束.由于Cassandra无法使用JOIN ...

  8. Cassandra数据建模

    1.  概述 Apache Cassandra将数据存储在表中,每个表都由行和列组成.CQL(Cassandra查询语言)用于查询存储在表中的数据.Apache Cassandra数据模型基于查询并针 ...

  9. 【翻译】ScyllaDB数据建模的最佳实践

    文章翻译自Scylla官方文档:https://www.scylladb.com/2019/08/20/best-practices-for-data-modeling/ 转载请注明出处:https: ...

随机推荐

  1. Virtual Directory in IIS

    https://www.iis.net/configreference/system.applicationhost/sites/site/application/virtualdirectory O ...

  2. HIToj--1076--Ordered Fractions(水题)

    Ordered Fractions   Source : Unknown   Time limit : 3 sec   Memory limit : 32 M Submitted : 1510, Ac ...

  3. django 笔记2

    默默坚持 :路由系统 URL :视图 request.GET request.POST request.FILES #checkbox等多选的内容 request.POST.getlist() #上传 ...

  4. android学习笔记二、Activity深入学习

    一.创建和使用: 1.Activity是android的四大组件之一,需要继承Activity并在清单文件中进行声明才能使用.没有声明则报错. 2.启动Activity是通过Intent,有两种方式: ...

  5. Container详解

    Container是一个拥有绘制.定位.调整大小的widget. padding和margin padding和margin分别设置Container的内边距和外边距.可取值包括下面四个: EdgeI ...

  6. org.xml.sax.SAXParseException: Content is not allowed in prolog

    sax错误:org.xml.sax.SAXParseException: Content is not allowed in prolog解决  标签: org. xml. sax. saxparse ...

  7. Python正则表达式初识(二)

    前几天给大家分享了Python正则表达式初识(一),介绍了正则表达式中的三个特殊字符“^”.“.”和“*”,感兴趣的伙伴可以戳进去看看,今天小编继续给大家分享Python正则表达式相关特殊字符知识点. ...

  8. 这是一套Java菜鸟到大牛的学习路线之高级教程,由工作了10年的资深Java架构师整理。

    这是一套Java菜鸟到大牛的学习路线之高级教程,由工作了10年的资深Java架构师整理.        01-java高级架构师设计-基础深入        J2SE深入讲解        Java多 ...

  9. [Python] Read and Parse Files in Python

    This lesson will teach you how to read the contents of an external file from Python. You will also l ...

  10. [Java开发之路](9)对象序列化与反序列化

    1. 对象序列化 当你创建对象时.仅仅要你须要.它会一直存在,可是程序终止时,不管何时它都不会继续存在.虽然这样做是很有意义的,可是在某些情况下.假设程序不执行时扔能存在而且保存其信息,那将对我们很实 ...