JanusGraph是以邻接列表存储的,这意味着图形存储为邻接列表的顶点集合。顶点的邻接列表包含全部点的边(出边和入边,包含边的属性)和顶点对应的属性。 JanusGraph按排序顺序维护邻接列表中的每一个顶点,其顺序由排序键和边标签的排序顺序定义。排序顺序容许使用以顶点为中心的索引有效地检索邻接列表的子集。 JanusGraph图形的邻接列表能够存储在支持Bigtable数据模型的任何存储后端中。 对于图形的存储,对于图的拆分格式有两种方式:按点切割、按边切割。html
经过以邻接列表格式存储图形,JanusGraph确保全部顶点的边和属性紧密地存储在存储后端中(好比Hbase\Cassandra等),从而能够加速遍历。缺点是每一个边必须存储两次一次做为source顶点的出边被存储,一次做为target顶点入边被存储,固然这也使咱们能够在source Vertex和target Vertex中任意顶点均可以快速找到对端。java
来自官网的示意图: sql
来自官网的示意图: 数据库
好比咱们下面有一个图, 后端
其组成图为(腾讯云社区): 数组
下面来自官网的示意图: bash
深蓝色框表示使用可变长度编码方案编码的数字,以减小它们消耗的字节数。红框表示使用关联属性键中引用压缩元数据序列化的一个或多个属性值(即对象)。灰色框表示未压缩的属性值(即序列化对象)数据结构
上图中咱们能够看出,Edge和Property在cell中都是由column(列)和value(值)组成。 Edge中column由labelid(边标签id)+direction(边的方向,相对于节点的出边或者入边)+sort key(用于边排序的key)+adjacent vertex id(临近顶点的id)+edge id(边id)组成,value由signature key(签名密匙)+other properties(边的其余属性)组成。并发
注意:此处的组成元素SortKey是一种特殊的属性,JanusGraph容许在定义Edge Label时指定其中的一个或多个属性为Sort Key,主要的做用是:将数据序列化进行存储时,序列化中edge会根据你设定的sort key进行排序,好比A有多个朋友关系的edge,每个edge都有一个创建时间(createtime),sort key即可以在存储时将边按照创建时间进行顺序存储,这样便于查找某个createtime的边,也便于范围查找。post
此处的signature key观看源码其实就是一个list数组, 里面存储的是边的property的key id(注意不是property id),做用是:边的other properties是被序列化存储在磁盘中,当咱们查找 边是否包含某一属性时不可能将其序列化回来再进行查找,这时候signature key的做用就体现出来了,经过其就能够知道这条边有什么属性,就能够更快的进行查找。如今再看‘红框表示使用关联属性键中引用压缩元数据序列化的一个或多个属性值’这句话,说的就是我引用属性的key id 。 signature key有一种空间的换时间的感受。。
Property中column由key id(属性的键id)组成,value由属性id+属性值组成。
这里注意key id 和 property id,key id 是属性key的id,举个栗子:name:李阳,这里的key id就是name这个property key的id,而name:李阳总体有一个id就是property id 了
一个Property Key所关联的属性值有可能有一个,也有可能有多个,所以,JanusGraph使用Cardinality来描述Property Key的这种特色。有SINGLE,LIST和SET三种类型, 源码中的PropertyKey接口能够看到:
public interface PropertyKey extends RelationType {
Class<?> dataType();
Cardinality cardinality();
}
复制代码
Cardinality为SINGLE时的存储结构,HBase的列名只存储Property Key的ID。具体的Property Value值以及Property ID(JanusGraph为每个Property分配的惟一ID),都存放在Cell的Value中。另外,若是该Property还有额外的Remaining properties,也会放在Value中。Remaining properties通常不使用,仅在一些特殊场景下,用于为该Property记录更多的附加信息(好比存储元数据Edge Labe的定义等)。
Candinality为LIST时的存储结构,各个部分与Cardinality为SINGLE时的结构类似,区别在于属性的ID被放在了列名中,而不是放在Value中。
Candinality为SET存储结构,各个部分与Cardinality为SINGLE时的结构类似,区别在于属性的值被放在了列名中,而不是放在Value中,前提是去除了重复。
JanusGraph的Property,在不一样的Cardinality下,数据存储结构略有不一样。总体原则是:根据Cardinality的不一样,列名自己可以肯定惟一的一个属性便可。
默认的多重性是MULTI
Property Key和Edge Label被抽象成了Relation Type,并采用相同的数据结构。因此说 Property Key和Edge Label不能被设置为相同的名字。
每一个边和属性都做为一个cell存储在其相邻顶点的行中。它们会被序列化而且column的字节顺序会遵循edge 的column中的sort key进行存储。变量id编码方案和压缩对象序列化使每一个edge/cell的存储所占空间都尽量小。 边的序列化从边标签的惟一ID开始(由JanusGraph指定)。这一般是一个小数字,而且使用变量id编码进行压缩。该id的最后一位是偏移量,用于存储这个边是入边(in)仍是出边(out)。接下来,存储包括sort key 的属性值,它是使用edge label定义的,所以排序键对象元数据能够引用边缘标签。以后,存储相邻顶点的id。JanusGraph不存储实际的顶点id,而是存储拥有此邻接列表的顶点的id。顶点id后跟此边的id,JanusGraph为每条边分配了一个惟一的id。这就是edge cell的column。edge的cell的column包含边的压缩序列化后的签名属性(由标签的签名键定义)以及未压缩序列化的边的任何其余属性。 属性的序列化表示更简单,column中只包含属性的键ID。属性id和属性值存储在value中。可是,若是将属性键定义为list()或者set(),则property id也存储在column中(上面property存储中说到过)。
从上述来看,咱们能够知道,JanusGraph图的schema该怎样定义主要是由edge labels 、property keys 和vertex labels 组成(Each JanusGraph graph has a schema comprised of the edge labels, property keys, and vertex labels used therein),JanusGraph的schema能够显式或隐式建立,推荐用户采用显式定义的方式。JanusGraph的schema是能够在使用过程当中修改的,并且不会致使服务宕机,也不会拖慢查询速度。,好比一个简单的显示定义的销售图的scheme:
<propertyKey value="salesman_id" explain="销售人员id" index="true" type="java.lang.String" />
<propertyKey value="real_name" explain="姓名" index="" type="java.lang.String" />
<propertyKey value="role" explain="角色" type="" />
<propertyKey value="city_code" explain="所处城市代码" index="" type="" />
<propertyKey value="create_time" explain="建立时间" index="" type="" />
<edgeLabel value="saleman_service_for" explain="销售引导">
<propertys>
<property value="create_time"/>
</propertys>
</edgeLabel>
<edgeLabel value="own_salaman_Idcard" explain="销售身份">
<propertys>
<property value="create_time"/>
</propertys>
</edgeLabel>
<index elementType="vertex" indexType="compositeIndex" name="salesman_id_I" >
<propertyKeys>
<propertyKey value="salesman_id" />
</propertyKeys>
</index>
<vertexLabel value="salesman" explain="销售" >
<propertys>
<property value="salesman_id" />
<property value="real_name" />
<property value="role" />
<property value="city_code" />
</propertys>
<edges>
<edge value="saleman_service_for" direction="out" />
<edge value="own_salaman_Idcard" direction="out" />
</edges>
</vertexLabel>
复制代码
固然,咱们也能够添加一些其余的能够组成schema的元素,上述三个是必须的,另外的好比索引(index)等,主要的结构仍是:
JanusGraph Schema
|-----------Vertex Lables
|-----------Property Keys
|-----------Edge Labels
复制代码
和通关系型数据库不一样,图数据的schema是定义一张图,而非定义一个vertex的。在Mysql中,咱们一般将创建一张表定义为建立一个schema,而在JanusGraph中,一个Graph用于一个schema。
若是转载此博文,请附上本文连接,谢谢合做~ :juejin.im/user/5c3036…
若是感受这篇文章对您有所帮助,请点击一下“喜欢”或者“关注”博主,您的喜欢和关注将是我前进的最大动力!