1. 索引类型

Janusgraph支持两种不同类型的索引来加速查询处理:graph indexes(图形索引) 和 vertex-centric indexes(顶点中心索引)。图形索引在通过属性定位出一批实体或者边的过程中有较好的性能,而顶点中心索引能够加速图的遍历速度,尤其是顶点具有很多边的时候。

2. 索引特性

2.1 图形索引(Graph indexes)

图形索引是整个图的全局索引结构,通过对实体或者边的属性进行索引来获得更好的选择性,从而加快图遍历的速度。
比如 以下两个检索操作:

g.V().has('name', 'haizhi')
g.E().has('reason', textContains('loves'))

第一个检索是查询出名称为haizhi的所有顶点,第二个检索操作是检索出边的reason属性中含有loves单词,如果没有对这两个属性没有建立索引,这两个操作都会导致全表扫描,效率非常低效。
图形索引分为两种类型:Composite index (组合索引)和 Mixed index(混合索引)

2.1.1 组合索引(Composite Index)

组合索引通过一个或者一组属性组成的固定的属性组合进行等值检索,这些属性必须是预定义且是固定顺序的。
组合索引支持唯一约束,设置为unique,则该属性组合必须保证唯一性。
排序在内存中,成本高。

2.1.2 混合索引(Mixed Index)

使用混合索引遍历顶点或边的时候,可以使用任何预先添加的属性key的组合。混合索引比组合索引更灵活,支持更多的条件谓词,而组合索引只支持相等判断查询。混合索引比组合索引查询速度要慢。
和组合索引不同,混合索引需要配置索引后端,如elasticsearch, solr, luncen。
混合索引支持全文检索、范围查询、地理位置查询等,并且不支持唯一性检查。
排序效率高。

2.2 顶点中心索引(Vertex-centric indexes)

顶点中心索引是为每个顶点建立的本地索引结构,当在大型的graph中,每个vertex存在数千条或者更多的edge,对这些vertex遍历会存在对这些edge的过滤,遍历效率较低,顶点中心索引能够通过本地索引结构加快索引遍历。该索引只支持最左匹配

3.索引生命周期

3.1 索引状态

我们的目标是从索引开始,通过一系列action,最终使索引进入ENABLED状态。
一个索引只能是处于以下几个状态中的一种

  • INSTALLED The index is installed in the system but not yet registered with all instances in the cluster
  • REGISTERED The index is registered with all instances in the cluster but not (yet) enabled
  • ENABLED The index is enabled and in use
  • DISABLED The index is disabled and no longer in use

3.2 索引操作

可以使用 mgmt.updateIndex()对索引进行以下操作

  • REGISTER_INDEX Registers the index with all instances in the graph cluster. After an index is installed, it - must be registered with all graph instances
  • REINDEX Re-builds the index from the graph
  • ENABLE_INDEX Enables the index so that it can be used by the query processing engine. An index must be registered before it can be enabled.
  • DISABLE_INDEX Disables the index in the graph so that it is no longer used.
  • REMOVE_INDEX Removes the index from the graph (optional operation). Only on composite index.

4. 操作索引

索引创建问题
在创建索引的过程中,按照官方给的示例创建索引,发现一直处于INSTALLED状态,无同转变成ENABLED,导致无法对索引REINDEX操作

mgmt = graph.openManagement()
name = mgmt.getPropertyKey('name')
mgmt.buildIndex('byNameComposite',Vertex.class).addKey(name).buildCompositeIndex()
mgmt.commit()
//等待索引生效  (这里有可能发生超时错误)
mgmt.awaitGraphIndexStatus(graph,'byNameComposite').call()
//此时查看会索引会一直处于INSTALLED状态
mgmt = graph.openManagement()
mgmt.printIndexes();
---------------------------------------------------------------------------------------------------
Vertex Index Name              | Type        | Unique    | Backing        | Key:           Status |
---------------------------------------------------------------------------------------------------
byNameComposite                | Composite   | false     | internalindex  | name:       INSTALLED |
---------------------------------------------------------------------------------------------------
Edge Index (VCI) Name          | Type        | Unique    | Backing        | Key:           Status |
---------------------------------------------------------------------------------------------------
Relation Index                 | Type        | Direction | Sort Key       | Order    |     Status |
---------------------------------------------------------------------------------------------------

解决办法

创建字段和创建索引需要处于同一个事务中。创建的索引状态会变成ENABLED,这会造成一个限制,如果想对已经存在的数据无法建立索引
mgmt = graph.openManagement();
//这里创建属性
name = mgmt.makePropertyKey('name').dataType(String.class).cardinality(org.janusgraph.core.Cardinality.SINGLE).make();
mgmt.buildIndex('byNameComposite',Vertex.class).addKey(name).buildCompositeIndex()
mgmt.commit()
mgmt = graph.openManagement();
mgmt.printIndexes()
---------------------------------------------------------------------------------------------------
Vertex Index Name              | Type        | Unique    | Backing        | Key:           Status |
---------------------------------------------------------------------------------------------------
byNameComposite                | Composite   | false     | internalindex  | name:         ENABLED |
---------------------------------------------------------------------------------------------------
Edge Index (VCI) Name          | Type        | Unique    | Backing        | Key:           Status |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
Relation Index                 | Type        | Direction | Sort Key       | Order    |     Status |
---------------------------------------------------------------------------------------------------

在混合索引中可以先创建一个ENABLED状态的索引,然后再添加已有的字段来规避这个问题

address = mgmt.makePropertyKey('address').dataType(String.class).cardinality(org.janusgraph.core.Cardinality.SINGLE).make();
mgmt.buildIndex('address_mixed_index',Vertex.class).addKey(address).buildMixedIndex("search")
mgmt.commit()
mgmt = graph.openManagement()
mgmt.printIndexes()
==>------------------------------------------------------------------------------------------------
Vertex Index Name              | Type        | Unique    | Backing        | Key:           Status |
---------------------------------------------------------------------------------------------------
byNameComposite                | Composite   | false     | internalindex  | name:         ENABLED |
address_mixed_index            | Mixed       | false     | search         | address:      ENABLED |
---------------------------------------------------------------------------------------------------
Edge Index (VCI) Name          | Type        | Unique    | Backing        | Key:           Status |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
Relation Index                 | Type        | Direction | Sort Key       | Order    |     Status |
---------------------------------------------------------------------------------------------------//获取之前创建的name索引,将该字段加到混合索引中
name = mgmt.getPropertyKey('name');
address_mixed_index = mgmt.getGraphIndex('address_mixed_index');
mgmt.addIndexKey(address_mixed_index, name)
mgmt.commit()
mgmt = graph.openManagement()
//此时查看索引的状态为 REGISTERED
mgmt.printIndexes()
==>------------------------------------------------------------------------------------------------
Vertex Index Name              | Type        | Unique    | Backing        | Key:           Status |
---------------------------------------------------------------------------------------------------
byNameComposite                | Composite   | false     | internalindex  | name:         ENABLED |
address_mixed_index            | Mixed       | false     | search         | name:      REGISTERED ||             |           |                | address:      ENABLED |
---------------------------------------------------------------------------------------------------
Edge Index (VCI) Name          | Type        | Unique    | Backing        | Key:           Status |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
Relation Index                 | Type        | Direction | Sort Key       | Order    |     Status |
---------------------------------------------------------------------------------------------------//再对索引进行REINDEX操作
mgmt = graph.openManagement()
mgmt.updateIndex(mgmt.getGraphIndex("address_mixed_index"),SchemaAction.REINDEX).get()
mgmt.commit()
//此时状态都是 ENABLED
mgmt.printIndexes()
==>------------------------------------------------------------------------------------------------
Vertex Index Name              | Type        | Unique    | Backing        | Key:           Status |
---------------------------------------------------------------------------------------------------
byNameComposite                | Composite   | false     | internalindex  | name:         ENABLED |
address_mixed_index            | Mixed       | false     | search         | name:         ENABLED ||             |           |                | address:      ENABLED |
---------------------------------------------------------------------------------------------------
Edge Index (VCI) Name          | Type        | Unique    | Backing        | Key:           Status |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
Relation Index                 | Type        | Direction | Sort Key       | Order    |     Status |
---------------------------------------------------------------------------------------------------

4.1 Composite index

Comosite index通过一个或多个固定的key组合 来获取Vertex Key或Edge,也即查询条件是在Index中固定的。

4.1.1 创建索引
//开启management并创建字段
mgmt = graph.openManagement()
name = mgmt.makePropertyKey('name').dataType(String.class).cardinality(org.janusgraph.core.Cardinality.SINGLE).make()
age = mgmt.makePropertyKey('age').dataType(Integer.class).cardinality(org.janusgraph.core.Cardinality.SINGLE).make()// 构建根据name查询vertex的组合索引
mgmt.buildIndex('byNameComposite',Vertex.class).addKey(name).buildCompositeIndex()// 构建根据name和age查询vertex的组合索引
mgmt.buildIndex('byNameAndAgeComposite',Vertex.class).addKey(name).addKey(age).buildCompositeIndex()mgmt.commit()

4.1.2 重建索引

mgmt = graph.openManagement()
mgmt.updateIndex(mgmt.getGraphIndex("byNameComposite"),SchemaAction.REINDEX).get()
mgmt.updateIndex(mgmt.getGraphIndex("byNameAndAgeComposite"),SchemaAction.REINDEX).get()
mgmt.commit()

需要注意的是,Composite index需要在查询条件完全匹配(必须该索引中所有字段全部用上才可以触发索引)的情况下才能触发,如上面代码,g.V().has(‘name’, ‘hercules’)和g.V().has(‘age’,30).has(‘name’,‘hercules’)都是可以触发索引的,但g.V().has(‘age’,30)则不行,因并未对age建索引。g.V().has(‘name’,‘hercules’).has(‘age’,inside(20,50))也不可以,因只支持精确匹配,不支持范围查询。

4.1.3 唯一索引使用

Composite Index也可以作为图的属性唯一约束使用,如果composite graph index被设置为unique(),则只能存在最多一个对应的属性组合。

mgmt = graph.openManagement()
name = mgmt.makePropertyKey('name').dataType(String.class).cardinality(org.janusgraph.core.Cardinality.SINGLE).make()
mgmt.buildIndex('byNameUnique',Vertex.class).addKey(name).unique().buildCompositeIndex()
mgmt.commit()

4.2 Mixed index

Mixed Index支持通过其中的 任意key的组合 查询Vertex或者Edge。Mix Index使用上更加灵活,而且支持范围查询等(不仅包含相等);从另外一方面说,Mixed index效率要比Composite Index低。
与Composite key不同,Mixed Index需要配置索引后端,JanusGraph可以在一次安装中支持多个索引后端,而且每个索引后端必须使用JanusGraph中配置唯一标识:称为indexing backend name。

4.2.1 创建索引
mgmt = graph.openManagement()
name = mgmt.makePropertyKey('name').dataType(String.class).cardinality(org.janusgraph.core.Cardinality.SINGLE).make()
age = mgmt.makePropertyKey('age').dataType(String.class).cardinality(org.janusgraph.core.Cardinality.SINGLE).make()
mgmt.buildIndex('nameAndAge',Vertex.class).addKey(name).addKey(age).buildMixedIndex("search")
mgmt.commit()

上面的代码建立了一个名为nameAndAge的索引,该索引使用name和age属性构成,并设定其索引后端为"search",对应到配置文件中为:index.serarch.backend,如果叫solrsearch,则需要增加:index.solrsearch.backend配置。
//这些操作会触发创建的nameAndAge索引

g.V().has('name', textContains('hercules')).has('age', inside(20,50))
g.V().has('name', textContains('hercules'))
g.V().has('age', lt(50))
4.2.2 添加属性

对已经存在的索引新增属性

mgmt = graph.openManagement()
//创建一个新的属性
location = mgmt.makePropertyKey('location').dataType(Geoshape.class).make()
nameAndAge = mgmt.getGraphIndex('nameAndAge')//修改索引
mgmt.addIndexKey(nameAndAge, location)
mgmt.commit()//对已经存在的数据重建索引
mgmt = graph.openManagement()
mgmt.updateIndex(mgmt.getGraphIndex("nameAndAge"),SchemaAction.REINDEX).get()
mgmt.commit()
4.2.3 对指定的lable数据建立索引

有些情况下,我们不想对图中具有某一label的所有Vertex或Edge进行索引,例如,我们只想对有GOD标签的节点进行索引,此时我们可以使用indexOnly方法表示只索引具有某一Label的Vertex和Edge。如下:

//Never create new indexes while a transaction is activegraph.tx().rollback()
mgmt = graph.openManagement()
name = mgmt.makePropertyKey('name').dataType(String.class).cardinality(org.janusgraph.core.Cardinality.SINGLE).make()
god = mgmt.makeVertexLabel('god').dataType(String.class).cardinality(org.janusgraph.core.Cardinality.SINGLE).make()//只索引有god这一label的顶点
mgmt.buildIndex('byNameAndLabel',Vertex.class).addKey(name).indexOnly(god).buildCompositeIndex()
mgmt.commit()

4.3 Vertex-centric indexes

Vertex-centric index(顶点中心索引)是为每个vertex建立的本地索引结构,在大型graph中,每个vertex有数千条Edge,在这些vertex中遍历效率将会非常低(需要在内存中过滤符合要求的Edge)。Vertex-centric index可以通过使用本地索引结构加速遍历效率,组合索引只支持最左匹配原则
如:

h = g.V().has('name','hercules').next()
g.V(h).outE('battled').has('time', inside(10,20)).inV()

如果没有vertex-centric index,则需要便利所有的batteled边并找出记录,在边的数量庞大时效率非常低。
建立一个vertex-centric index可以加速查询:

//Never create new indexes while a transaction is activegraph.tx().rollback()
mgmt = graph.openManagement()//找到一个property key
time = mgmt.makePropertyKey('time').dataType(String.class).cardinality(org.janusgraph.core.Cardinality.SINGLE).make()
// 找到一个label
battled = mgmt.getEdgeLabel('battled')// 创建vertex-centric index
mgmt.buildEdgeIndex(battled,'battlesByTime',Direction.BOTH,Order.decr, time)
mgmt.commit()//Wait for the index to become available
mgmt.awaitGraphIndexStatus(graph,'battlesByTime').call()//Reindex the existing data
mgmt = graph.openManagement()
mgmt.updateIndex(mgmt.getGraphIndex("battlesByTime"),SchemaAction.REINDEX).get()
mgmt.commit()

上面的代码对battled边根据time以降序建立了双向索引。buildEdgeIndex()方法中的第一个参数是要索引的Edge的Label,第二个参数是index的名称,第三个参数是边的方向,BOTH意味着可以使用IN/OUT,如果只设置为某一方向,可以减少一半的存储和维护成本。最后两个参数是index的排序方向,以及要索引的property key,property key可以是多个,order默认为升序(Order.ASC)。

如果觉得有帮助可以关注公众号获取更多的文章

Janusgraph索引相关推荐

  1. 【JanusGraph】第三章: 入门

    本节中的例子展示了如何使用JanusGraph检索诸神关系图. 关系图如下图所示.抽象数据模型使用大家都熟知的Property Graph Model ,而且这个例子描述了罗马诸神中的人物和他们所在位 ...

  2. JanusGraph 入门

    Getting Started http://docs.janusgraph.org/latest/getting-started.html JanusGraph 第三章 入门 本节中的例子展示了如何 ...

  3. 【图解图数据库系列】- 文章总目录(定时更新)

    前言 本系列博文会不断更新和修改,大家可以收藏该文章或关注博主,便于以后的查找: 本次更新时间:2022/07/07日 博主从2018年因为业务原因开始接触图数据库,写该系列文章的目的主要是在图库使用 ...

  4. JanusGraph报错:Unknown external index backend

    使用java连接JanusGraph进行创建图操作,报错地方是程序运行第50行代码其作用是生成混合索引,截图如下: 后在0.6版本官方文档发现有说明先贴一份截图: 具体说明如下: The exampl ...

  5. java 连接janusgraph_基于JanusGraph的大数据图数据库

    导读 知识图谱是近来很火的概念,很多领域都希望能用知识图谱解决一些问题.在零售领域其实也有使用知识图谱的场景,比如阿里使用知识图谱进行商品智能导购以及商品"巡检",而我想试验着把知 ...

  6. java对象底层原存储结构图解_图解图库JanusGraph系列-一文知晓“图数据“底层存储结构...

    大家好,我是洋仔,JanusGraph图解系列文章,实时更新~ 图数据库文章总目录: 转载文章请保留以下声明: 一:存储模式 留言或私信我,邀请你加入"图数据库交流"微信群! 1. ...

  7. JanusGraph 安装

    下载地址:https://github.com/JanusGraph/janusgraph/releases/ 版本:Version 0.3.2 (June 16, 2019) 安装 解压 janus ...

  8. janusgraph整合mysql_图解图库JanusGraph系列-一文知晓“图数据“底层存储结构

    527-7.jpg 大家好,我是洋仔,JanusGraph图解系列文章,实时更新~ 图数据库文章总目录: 版本:JanusGraph-0.5.2 转载文章请保留以下声明: 一:存储模式 留言或私信我, ...

  9. 1. JanusGraph的优势

    JanusGraph 旨在提供不止一台机器的图数据的存储和计算能力.实时的图数据遍历和分析查询是JaunsGraph的基本特性.本节将讲解JanusGraph的特性和所支持的底层持久性解决方案. Ja ...

  10. 图解Janusgraph系列-查询图数据过程源码分析

    图解Janusgraph系列-查询图数据过程源码分析 大家好,我是洋仔,JanusGraph图解系列文章,实时更新~ 图数据库文章总目录: 整理所有图相关文章,请移步(超链):图数据库系列-文章总目录 ...

最新文章

  1. 共享内存生产者消费者模型
  2. 【echart数组数据】echarts两条或两条以上x轴不同的线合并x轴 含有不连续数据
  3. 前端开发自学之JavaScript——显示当前时间
  4. Android官方开发文档Training系列课程中文版:手势处理之记录手指移动的轨迹
  5. make pycaffe 报错:“fatal error: numpy/arrayobject.h: No such file or directory” 解决方案
  6. 推导基姆拉尔森公式根据日期计算星期
  7. Hadoop1.0之集群搭建
  8. [codeup 2134] FatMouse's Trade
  9. 暴风影音 打开 avi 视频文件时 explorer 出错 关闭
  10. matlab多项式运算开方,matlab多项式运算【技术材料】
  11. 2021考研数学二汤家凤接力题典1800【题目册】
  12. python npv 计算公式_Python中IRR的计算
  13. springboot整合阿里云OSS存储(对象存储)图文详解-———入门操作指南。
  14. java monitor怎么使用_Java monitor机制使用方法解析
  15. Android10闪退无日志,【报Bug】Android10手机白屏闪退
  16. 样本量太小怎么做结构方程模型?
  17. FZU 1968 Twinkling lights III
  18. 加入计算机网络协会申请书,大学生退出协会申请书
  19. springboot实现短信发送验证码及消息队列发送注册成功短信
  20. 配置windows iis

热门文章

  1. 文档转换工具 —— 你还在为wps的word转pdf上限五页而苦恼吗?
  2. linux下安装jemalloc
  3. 服务器虚拟网卡驱动卸载,Win10安装和卸载万能网卡版驱动的方法
  4. 论文泛读: 基于改进退化隐马尔可夫模型的设备健康诊断与寿命预测研究
  5. 图(深度优先遍历、广度优先遍历)
  6. linux超级块编辑,在EXT4 linux系统上模拟丢失的超级块错误
  7. Labview与三菱PLC通讯 (2)
  8. maven setting文件存放位置
  9. LPDDR4协议规范之(二)复位和上电初始化
  10. 《跟阿铭学linux》(第3版)笔记