背景

简单分析一下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. EdgeRDDVertexRDD生成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. Concurrent.Thread.js

    (function(){ if ( !this.Data || (typeof this.Data != 'object' && typeof this.Data != 'functi ...

  2. 我比xx强在哪里?弱在哪里?

    向下管理? 向上管理? 自我形象? 人机关系运作? 弱项不在管理方面: 在向上的人际关系处理和机会把握方面.

  3. javaScript for in循环遍历对象

    for循环常被我们用来遍历数组,而如何遍历对象呢? 这时就需要用到for in循环了 写一个遍历对象名简写如下: for(var xxx in ooo){console.log(xxx)} 其中xxx ...

  4. JS对象继承与原型链

    1.以复制方式实现的继承 1.1浅拷贝 基本类型的复制 var parent = { lanage: "chinese" } var child = { name: "x ...

  5. 昼猫笔记 -- 面向对象(II) - 继承

    继承 由于js不像java那样是真正面向对象的语言,js是基于对象的,它没有类的概念. 所以,要想实现继承,可以用js的原型prototype机制或者用apply和call方法去实现,还有就是js可以 ...

  6. XML解析——SAX解析以及更方便的解析工具(JDOM、DOM4J)

    XML主要用于数据交换,HTML则用于显示. 相对于DOM的树形解析,SAX采用的是顺序解析,这种解析方法可以快速地读取XML数据的方式. SAX主要事件: No. 方法 类型 描述 1 public ...

  7. HttpComponents入门解析

    1 简介 超文本传输协议(http)是目前互联网上极其普遍的传输协议,它为构建功能丰富,绚丽多彩的网页提供了强大的支持.构建一个网站,通常无需直接操作http协议,目前流行的WEB框架已经透明的将这些 ...

  8. struts2 结合extjs实现的一个登录实例

    一.先搭建好struts2,能够通过myeclipse高速搭建. 二.再导入extjs所需的库文件. 三.写一个实体类User package com.ext.model; public class ...

  9. Linq查询案例

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  10. Onvif开发之服务端成功对接Rtsp视频流篇

    前面篇介绍onvif服务端的发现功能,继续在之前的代码基础上完成一个RTSP流的工作,也就是客户端通过ONVIF协议来预览设备端在这个之前必须确定几个简单的条件1 设备端能被发现2 设备端支持RTSP ...