主流图数据库Neo4J、ArangoDB、OrientDB综合对比:架构分析

    <!-- 作者区域 -->
<div class="author">
<a class="avatar" href="/u/eed250c63d5d">
<img src="//upload.jianshu.io/users/upload_avatars/6065901/08294949-cd9e-4a1e-9d35-26be089dc5b0?imageMogr2/auto-orient/strip|imageView2/1/w/96/h/96" alt="96">



YOTOY



关注







0.4





2017.06.15 15:11*

字数 3733

阅读 16430评论 2喜欢 18


    <!-- 文章内容 -->
<div data-note-content="" class="show-content">
<div class="show-content-free">
<p>1: 本地存储方式<br>

2: 内置查询语言分析

3: 性能分析

4: 图算法支持


本地存储方式

Neo4J

neo4j数据库支持最大多少个节点?最大支持多少条边?

  • 目前累积统计它有34.4亿个节点,344亿的关系,和6870亿条属性。

在数据库中,读/写性能跟节点/边的数量有关吗?

  • 这个问题意味着两个不同的问题。单次读/写操作不依赖数据库的大小。不管数据库是有10个节点还是有1千万个都一样。 — 然而,有一个事实是如果数据库太大,你的内存可能无法完全缓存住它,因此,你需要频繁的读写磁盘。虽然很多用户没有这样大尺寸的数据库,但有的人却有。如果不巧你的数据库达到了这个尺寸,你可以扩展到多台机器上以减轻缓存压力。

是否有备份恢复机制?

  • Neo4j 企业版提供了一个在线备份(完整备份和增量备份)功能。

写数据库是线程安全的吗?

  • 不管在单服务模式还是HA模式,数据库在更新之前都通过锁定节点和关系来保证线程安全。

文件存储结构

node,relationship,property存储都是固定大小的。 如下图:

  • 固定大小可以快速查找,基于此,可以直接计算一个节点的位置,时间复杂度$O(1)$,比查询的$O(log n)$快。
image.png

节点

存储文件neostore.nodestore.db

  • 第一个字节,是否被使用的Flag
  • 下4个字节,代表第一个关系的ID,连接到这个节点上的 :ID
  • 紧接着的4个字符,代表第一个属性ID,连接到这个节点上的
  • 紧接着的5个字符是代表当前结点的Label,指向Label存储的。 :LABEL
  • 最后一个字符是标志字符,用来标志紧密相邻的点,或者留备后用。 这就是Neo4J索引实现的方案。Index-Free Adjacency

这些指向的ID都是链式ID中的第一个,比如关系ID是关系链中的第一个。


关系

存储文件neostore.relationshipstore.db

  • 1:同上
  • 1-5:第一个节点
  • 5-9:第二个节点
  • 9-13:关系类型 :TYPE
  • 13-21:前一个关系的前后节点 ID
  • 21-29:后一个关系的前后节点 ID
  • 29-33:属性ID
  • 34:是都是关系链中的第一个的标志

关系是双向链表,属性是单向链表


属性文件

存储文件neostore.propertystore.db

  • 每个属性文件包含4个属性块,一个指向下个属性的ID,在属性链中
  • 属性包括属性类型,指向属性索引文件neostore.propertystore.db.index的指针
    • 属性是键值对存储的,数据类型可以使用JVM的所有私有属性,加上字符串和数组类型;
    • 属性值也可以使用动态存储,就是大文件,类型如下:字符串&数组

查找时文件调用模型

image.png

  • 节点包含指向关系链和属性链的第一个指针。
  • 指向Label的指针,可能多个。
  • 属性读取从单向链表的第一个开始
  • 关系读取直接在双向链表中查找,直到找到想要的关系。

Index-Free Adjacency

查询时,算法复杂度,$O(n)$,$n$是节点数,其他常规索引的复杂度都是$O(n log n)$

删除修改一个有很多很多边的节点时会有点麻烦,因为没有常规索引,只能从关系链中开始删除。

  • 为了去除所有的事件边,你必须访问每个相邻的顶点,并且为每个相邻的顶点执行一个潜在的昂贵的移除操作。

ArangoDB

文档在ArangoDB中的存储格式非常类似JSON,叫做VelocyPack格式的二进制格式存储。

  • 文档被组织在集合中。
  • 有两种集合:文档(V),边集合(E)
  • 边集合也是以文档形式存储,但包含两个特殊的属性_from_to,这两个属性被用来创建在文档和文档之间创建关系

存储空间占用下:采用了元数据模式存储数据

  • 可通过内存提速,CPU占有率低。

索引

索引类型

  • Primary Index,默认索引,建立字段是_key_id上,一个哈希索引
  • Edge Index,默认索引,建立在_from_to上,哈希索引;不能用于范围查询、排序,弱于OrientDB
  • Hash Index,自建
  • Skiplist Index,有序索引,
    • 用于快速查找具有特定属性值的文档,范围查询以及按索引排序顺序返回文档。
    • 用于查找,范围查询和排序。补全范围查询的缺点。

Primary IndexEdge Index,是内存索引,文档加载速度很慢,推测是在重建索引。没有见到ArangoDB说有内存索引持久化。


  • Persistent IndexRocksDB的索引。

    • 持久性索引是具有持久性的排序索引。当存储或更新文档时,索引条目将写入磁盘。
    • 使用持久性索引可能会减少集合加载时间。
  • Geo Index,用户可以在集合中的一个或多个属性上创建其他地理索引。地理索引用于快速找到地球表面的地方。
  • Fulltext Index,全文索引

Hash查询很快,几乎为$O(1)$。


Novel Hybrid Index

image.png

把所有的边都存储在一个大哈希表中,把每个顶点V都放到一个双链表中。

  • 将节点放入链表中,遍历所有节点的复杂度时$O(k)$,k是节点总数。

    • 节点邻接点是通过边集确定的,边集的起始点和结束点都是默认Hash索引的,所以查找一个节点的时间复杂度是$O(1)$。
  • 遍历边的复杂度是$O(log E) + O(k)$,E是边的数量。
    • 边的遍历是通过遍历节点开始的。
    • 删除和修改边的时候,是通过节点的key查找的,确认边是不是节点的链表中的第一个,不是就通过链表继续找。
    • 边索引不仅是边集的索引,也是顶点的邻接点的索引。

存储引擎

在ArangoDB 3.0 这个版本,arangodb切换了自己的存储引擎,RocksDB

Persistent indexes via RocksDB is the first step of ArangoDB to persist indexes in general.

在docker下这个版本的ArangoDB的接口没有做好,挂在存储卷时会导致RocksDB IO异常。

架构变动很频繁。3.2版本还会引入pregel框架。

  • 数据库的Bug不但存在于本身还存在于其它引用的架构处。

OrientDB

索引类型

  • SB-Tree Index:从其他索引类型中获得的特性的良好组合,默认索引
  • Hash Index:
  • Auto Sharding Index:提供一个DHT实现;不支持范围查询
  • Lucene Spatial Index:持久化,支持事物,范围查询

在 Java中,如果哈希函数不合理,返回值过于集中,会导致大字典更慢。Java 由于存在链表和红黑树互换机制,搜索时间呈对数级增长,而非线性增长。在理想的哈希函数下,无论字典多大,搜索速度都是一样快。


SB-Tree Index

  • UNIQUE:这些索引不允许重复的键。对于复合索引,这指的是组合键的惟一性。
  • NOTUNIQUE:这些索引允许重复的键。
  • FULLTEXT:这些索引是基于任何单个文本的。可以通过CONTAINSTEXT操作符在查询中使用它们。
  • DICTIONARY:这些索引类似于使用惟一的索引,但是在重复键的情况下,它们用新的记录替换现有的记录。

Lucene Engine

  • FULLTEXT:这些索引使用Lucene引擎来索引字符串内容。可以在LUCENE操作符的查询中使用它们。
  • SPATIAL:这些索引使用Lucene引擎来索引地理空间坐标。

SB索引

SB索引,B树上优化了数据插入和范围查询,时间复杂度$O(log(N))$,其底数大约500。

  • 磁盘消耗大。

使用类似继承的方式去实现包含特殊属性的顶点集和边集。


OrientDB本地存储原则

OrientDB本地存储原则:使用包含由固定大小部分(页面)分割的磁盘数据并写入日志记录方法的磁盘缓存(当页面中的更改首先记录在所谓的持久存储器中时),我们可以实现以下特性:OrientDB 2.2.x——PLocal Engine

  • Operations on single page are atomic.
  • Changes applied to the page can be restored after server crash even if they were not flushed to the disk.

保护数据


image.png

集群实现就是通过Class的类似继承机制实现的分表。Clusters


内置查询语言分析

AQL

arangodarangosh是用CPP写的。

  • 网络/磁盘IO处理也是通过CPP写的
  • AQL执行器:CPP
  • AQL函数大部分是通过CPP写的,少部分是通过JS写的。
  • AQL调用的用户函数全是JS函数

但,arangodarangosh依赖V8 JS引擎

  • 所有的JS命令行进入arangosh都会被V8执行。
  • arangodJS孤岛,--javascript.v8-contexts,在多线程中用JS,但是JS本身还是单线程的。

类SQL语言,与ES6无缝连接,可以使用ES6语法。

  • JS的引入功能类似存储过程,提供Foxx框架
  • 以V8作为语句执行引擎,性能有问题,而且导致很多坑;
  • V8和Neo4J与OrientDB的JVM相比差距有点大,执行的性能感觉和Node.JS差不错,适合事物密集型而不适合计算密集型的程序。
  • 个人认为,arangosh使用V8的目的是通过异步回掉调用本地cpp代码提供计算性能,而不是使用V8去直接计算,所以在用各图数据库实现图算法的时候如果使用JS去实现的话,性能会不是那么的友善,对于ArangoDB值得期待的就是pregel将会在3.2版本面世。

Cypher

语义清晰,Neo4J唯一支持的语言

OrientDB SQL

类SQL,语法和SQL基本类似,冗长。


性能分析

少量数据分析

亿级数据分析

ArangoDB

arangoimp插入效率感人,推测原因:

  • 导入方式是边插入边建立索引的,可能性不高,因为同一数据集在多台主机上严重了其卡住的位置是不同的
  • 其hash函数设置不好,导致不停的哈希冲突,hash索引是arangodb的默认索引,可能性也不高;
  • 官网上有模糊的说明,arangodb的索引是存储在内存中的,官网特意说明Persistent Index这个索引是存储在磁盘上的,其他索引是需要在文档加载时候重新建立索引的。

arangoimp在默认情况下到达1300万数据之后导入性能很差。


在都没有支持复杂图算法的情况下,十万级数据ArangoDB的图计算效率比较低,因为是单线程JS在V8上运行的。

arangodb对于边的插入不支持批量插入:

  • arangosh中已经验证,其只能一条边一条边的插入,后面的数据会被无视掉。

arangoimp上存在无效参数:

  • 比如创建边集选项,无论是否选择是true,都不会创建,Github上官方解释必须在数据库中先创建边集才可以,也就是说这个命令中的创建边集的参数是一个无效参数。

Neo4J

neo4j-import导入数据很快。

root@ubuntu:/var/lib/neo4j/data/databases# neo4j-import --into njaq --nodes /home/dawn/csv/perosnInfo.csv --relationships /home/dawn/csv/know.csv  --skip-bad-relationships true --skip-bad-entries-logging true --bad-tolerance true
WARNING: neo4j-import is deprecated and support for it will be removed in a future
version of Neo4j; please use neo4j-admin import instead. Neo4j version: 3.2.1

Importing the contents of these files into njaq:

Nodes:

/home/dawn/csv/perosnInfo.csv

Relationships:

/home/dawn/csv/know.csv Available resources:

Total machine memory: 3.84 GB

Free machine memory: 1.61 GB

Max heap memory : 875.00 MB

Processors: 4

Configured max memory: 700.35 MB Nodes, started 2017-06-08 05:35:30.741+0000

[>:18.87 MB|NODE:152.59 MB----|*PROPERTIES(3)|LABEL SCAN--|v:37.14 MB/s-----------]20.0M ∆21.8K

Done in 51s 548ms

Prepare node index, started 2017-06-08 05:36:22.495+0000

[DETECT:419.62 MB----------------------------------------------------------------------------]20.0M ∆-6500000

Done in 9s 126ms

Relationships, started 2017-06-08 05:36:31.678+0000

[>:7|T|
PREPARE(4)=|RE|CALCULATE-|P|v:]79.9M ∆10.9K

Done in 4m 17s 742ms

Relationship --> Relationship 1/1, started 2017-06-08 05:40:49.548+0000

[>-----------------------------------------------------------------------|LINK------------|v:]79.9M ∆ 405K

Done in 2m 5s 784ms

RelationshipGroup 1/1, started 2017-06-08 05:42:55.404+0000

[
>:??----------------------------------------------------------------------------------------] 0 ∆ 0

Done in 11ms

Node --> Relationship, started 2017-06-08 05:42:55.439+0000

[>:13|>-------------------------------------------------|LIN|v:26.00 MB/s--------------------]19.9M ∆2.18M

Done in 11s 833ms

Relationship <-- Relationship 1/1, started 2017-06-08 05:43:07.308+0000

[
>-------------------------------------------------------------------------------|LINK----|v:]79.9M ∆ 168K

Done in 11m 29s 787ms

Count groups, started 2017-06-08 05:54:37.570+0000

[>:??----------------------------------------------------------------------------------------] 0 ∆ 0

Done in 1ms

Gather, started 2017-06-08 05:54:38.061+0000

[
>:??----------------------------------------------------------------------------------------] 0 ∆ 0

Done in 4ms

Write, started 2017-06-08 05:54:38.156+0000

[>:??----------------------------------------------------------------------------------------] 0 ∆ 0

Done in 15ms

Node --> Group, started 2017-06-08 05:54:38.213+0000

[
>:??----------------------------------------------------------------------------------------] 0 ∆ 0

Done in

Node counts, started 2017-06-08 05:54:38.264+0000

[*>(4)|COU]20.0M ∆80.0K

Done in 1m 26s 338ms

Relationship counts, started 2017-06-08 05:56:04.625+0000

[*>(4)==============|COUNT----------------------------]80.0M ∆1.81M

Done in 2m 47s 277ms IMPORT DONE in 23m 22s 420ms.

Imported:

20000000 nodes

79994052 relationships

80000000 properties

Peak memory usage: 899.62 MB

Neo4J使用导入方法之后会建立索引,否则基本没有性能,建立索引很快。


图算法支持

ArangoDB图算法支持

  1. AQL

    1. 遍历:从指定开始点,通过一定算法、边类型、图类型、深度获取与指定开始点相关连通的点。

      1. 数据源:图、边集合
      2. 边方向:出边、入边、全部
      3. 遍历方式:BFS Or DFS
    2. 最短路径:两点最短路径,选项基本和上面类型
  2. Pregel
    1. @arangodb/pregel 文件夹下,很多分布式的图算法
    2. PageRank
    3. CC 强弱连通算法
    4. 单源最短路径算法

JS扩展

  • 通过JS可以完成对内置算法的扩展,但是自定义方法是单线程JS函数,如果用来做算法,性能堪忧,最佳选择就是选择内置的方法去实现图算法。
  • 通过JS可以实现很多算法,但是在ArangoSH下代码单线程运作,虽然arangod的JS是在多线程中运行的,但是arangosh是在单线程中运行的,且JS本身并不擅长处理计算型代码,相比之下通过内置的数据库语言而不是这种内置语言与JS混杂方式的代码会快很多;比如Neo4J,OrientDB的查询语言。

Neo4J

对于普通的遍历最短路径算法支持和ArangoDB一样都支持,但Neo4J的图的遍历深度的阈值设置比较难,且深度超过6算法会效率比较低。

相比之下,ArangoDB的算法参数设置全部依赖于Key-Value实现,算法在编码层次灵活性很高。

对于PageRank,CC等算法的实现,Neo4J提供两种方式:

  • 编写Jar包,GitHub上有个未被官方承认的Jar包
  • Cypher直接实现

OrientDB

同上,图算法也支持Jar包导入。


内置图算法

最短路径

Cypher:

match (p1:person{no:'%s'}),(p2:person{no:'%s'}) match p=shortestPath((p1)-[*..3]->(p2)) return p

OrientDB SQL:

select dijkstra((select @RID from persons where no='%s'),(select @RID from persons where no='%s'),'E')

AQL:

for v,e in outbound shortest_path '%s' to '%s' graph 'graphPersons' return [v._key,e._key]

邻接点

Cypher:

MATCH (js:person)-[:know]-(surfer) WHERE js.no = '%s' return surfer

OrientDB SQL:

select from E where out = (select @RID from persons where no='%s

AQL:

traversal_results = graphPersons.traverse(
start_vertex='persons/'+getSingleInfo(id).no,
strategy='bfs',
direction='outbound',
edge_uniqueness='global',
vertex_uniqueness='global',
max_depth=1
)

参考资料

      </div>
</div>
</div>

主流图数据库Neo4J、ArangoDB、OrientDB综合对比:架构分析的更多相关文章

  1. 图数据库Neo4j

    官网下载:https://neo4j.com/download/ 图数据库Neo4j入门:https://blog.csdn.net/gobitan/article/details/68929118 ...

  2. 图数据库Neo4j简介

    图数据库Neo4j简介 转自: 图形数据库Neo4J简介 - loveis715 - 博客园https://www.cnblogs.com/loveis715/p/5277051.html 最近我在用 ...

  3. Hello World 之Spring Boot 调用图数据库Neo4j

    明日歌 [清]钱鹤滩 明日复明日,明日何其多! 我生待明日,万事成蹉跎 1. 图数据库Neo4j之爱的初体验 ----与君初相识,犹似故人归 在如今大数据(big data)横行的时代,传统的关系型数 ...

  4. 开源软件:NoSql数据库 - 图数据库 Neo4j

    转载自原文地址:http://www.cnblogs.com/loveis715/p/5277051.html 最近我在用图形数据库来完成对一个初创项目的支持.在使用过程中觉得这种图形数据库实际上挺有 ...

  5. (三)图数据库neo4j的安装配置

    (一)neo4j安装 neo4j有社区版本和企业版,社区版本是免费的,企业版本是收费的.在linux上安装如下步骤: 1.将下载的neo4j-enterprise-3.4.0-unix.tar.gz包 ...

  6. 知识图谱之图数据库Neo4j

    知识图谱中的知识是通过RDF结构来进行表示的,其基本单元是事实.每个事实是一个三元组(S, P, O),在实际系统中,按照存储方式的不同,知识图谱的存储可以分为基于表结构的存储和基于图结构的存储. 基 ...

  7. 图数据库neo4j和关系数据库的区别

    相信您和我一样,在使用关系型数据库时常常会遇到一系列非常复杂的设计问题.例如一部电影中的各个演员常常有主角配角之分,还要有导演,特效等人员的参与.通常情况下这些人员常常都被抽象为Person类型,对应 ...

  8. 图数据库Neo4j的基本使用及与SpringBoot集成

    Neo4j 官网地址:https://neo4j.com/ 下载地址:https://neo4j.com/download-center/#community 官方入门文档:https://neo4j ...

  9. linux环境图数据库neo4j安装

    自定义yum源 Neo4j Stable Yum Repo First, you'll want our key: cd /tmp wget http://debian.neo4j.org/neote ...

随机推荐

  1. deepin 安装版本管理工具

    在Linux下我们可以使用RapidSVN.RapidSVN是一款轻量级的免费.开源 SVN 客户端,相比tortoise svn它更加小巧而且占系统资源少运行速度快. 一:安装RapidSVN版本控 ...

  2. moiezen

    这题是个随机化+二分裸题--------考场上居然没有想出来--想的出来就怪了吧 我们随机一下增加x的顺序,然后进行二分之前,看看这个x加完之后能不能更新答案,不能就不二分了.具题解所说,这个复杂度是 ...

  3. Echarts和Quartz简介

    一.Echarts ​ ECharts 是由百度前端团队开发的一款开源的基于 js 图形报表组件,一个使用 JavaScript 实现的开源可视化库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大 ...

  4. opencv边缘滤波

    2018-03-0422:16:11 import cv2 as cv import numpy as np def bi_demo (image): print ("ceshi" ...

  5. Apache ab使用指南

    Apache ab使用图例: 其中比较重要的两个指标要特别注意: Requests per second:表示平均每秒事务数,相当于LR的TPS Time per second:用户请求平均响应时间和 ...

  6. Codeforces_766_D_(并查集)

    D. Mahmoud and a Dictionary time limit per test 4 seconds memory limit per test 256 megabytes input ...

  7. RocketMQ学习笔记(16)----RocketMQ搭建双主双从(异步复制)集群

    1. 修改RocketMQ默认启动端口 由于只有两台机器,部署双主双从需要四个节点,所以只能修改rocketmq的默认启动端口,从官网下载rocketmq的source文件,解压后使用idea打开,全 ...

  8. 解决[disabled]="true"与formControlName冲突

    import { FormBuilder } from '@angular/forms'; form; constructor(private fb: FormBuilder) { this.form ...

  9. 梦想MxWeb3D协同设计平台 2019.02.28更新

    梦想MxWeb3D协同设计平台 2019.02.28更新 SDK开发包下载地址: http://www.mxdraw.com/ndetail_10130.html 在线演示网址: http://www ...

  10. vue中websoket的使用

    首先安装npm install --save  websocket-heartbeat-js@^1.0.7 在main.js中  引入并挂载全局方法 import WebsocketHeartbeat ...