GraphX 图数据建模和存储

简介:

背景

简单分析一下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] = _

全文完 :)

目录
相关文章
|
6月前
|
数据采集 大数据 数据库
数据架构问题之流式架构的典型代表图示有吗
数据架构问题之流式架构的典型代表图示有吗
|
8月前
|
存储 数据挖掘 大数据
大数据数仓建模基础理论【维度表、事实表、数仓分层及示例】
数据仓库建模是组织和设计数据以支持数据分析的过程,包括ER模型和维度建模。ER模型通过实体和关系描述数据结构,遵循三范式减少冗余。维度建模,特别是Kimball方法,用于数据仓库设计,便于分析和报告。事实表存储业务度量,如销售数据,分为累积、快照、事务和周期性快照类型。维度表提供描述性信息,如时间、产品、地点和客户详情。数仓通常分层为ODS(源数据)、DWD(明细数据)、DIM(公共维度)、DWS(数据汇总)和ADS(应用数据),以优化数据管理、质量、查询性能和适应性。
2037 3
|
8月前
|
SQL 存储 NoSQL
GQL图查询语言:高效处理复杂图数据
GQL是一种新型的查询语言,它可以处理复杂图数据,以提供比传统 SQL更快、更高效的查询方式。GQL图查询语言具有可扩展性,可以使用最少的编程知识来访问图数据库。在本文中,我们将探讨 GQL的概念和实际使用案例。同时,我们还将提供一些 GQL的示例代码,以帮助您更好地了解和应用 GQL。
|
存储 数据挖掘 关系型数据库
数仓学习---6、数据仓库概述、 数据仓库建模概述、维度建模理论之事实表、维度建模理论之维度表
数仓学习---6、数据仓库概述、 数据仓库建模概述、维度建模理论之事实表、维度建模理论之维度表
|
SQL JSON 自然语言处理
数仓建模—建模工具PdMan
工欲善其事,必先利其器,所以开始数仓建模之前我们还是要选择一个合适的建模工具,江湖上混怎么能没有一个响亮的名号和趁手的武器呢,PDMan就是我们要介绍的工具。后面我们还会介绍其他建模工具,你选择一个合适的就行。
2078 0
数仓建模—建模工具PdMan
|
存储 SQL 分布式计算
图加速数据湖分析-GeaFlow和Hudi集成
本文主要分析了表模型的现状和问题,然后介绍了图模型在处理关系运算上的优势,接着介绍了图计算引擎GeaFlow和数据湖格式hudi的整合,利用图计算引擎加速数据湖上的关系运算.
图加速数据湖分析-GeaFlow和Hudi集成
|
大数据 数据管理 数据库
数据仓库(3)数仓建模之星型模型与维度建模
维度建模是一种将数据结构化的逻辑设计方法,也是一种广泛应用的数仓建模方式,它将客观世界划分为度量和上下文。度量是常常是以数值形式出现,事实周围有上下文包围着,这种上下文被直观地分成独立的逻辑块,称之为维度。它与实体-关系建模有很大的区别,实体-关系建模是面向应用,遵循第三范式,以消除数据冗余为目标的设计技术。维度建模是面向分析,为了提高查询性能可以增加数据冗余,反规范化的设计技术。
483 1
|
存储 数据采集 SQL
数仓建模—宽表的设计
其实宽表是数仓里面非常重要的一块,前面我们介绍过了维度表事实表,今天我们介绍一下宽表,前面我们说过了数仓是分层的,这是技术进步和时代变化相结合的产物,数仓的分层式为了更好地管理数仓以及更加高效地进行数据开发。宽表主要出现在dwd 层和报表层,当然有的人说dws 层也有,宽表,从字面意义上讲就是字段比较多的数据库表,通常情况下是将很多相关的数据包括维度表、实时、已有的指标或者是dws/dwd 表关联在一起形成的一张数据表。由于把不同的内容都放在同一张表存储,宽表已经不符合范式设计的模型设计规范而且数仓里面也不强调范式设计,随之带来的就是数据的大量冗余,与之相对应的好处就是查询性能的提高与便捷
2539 0
数仓建模—宽表的设计
|
存储 SQL 分布式计算

热门文章

最新文章