JanusGraph---Index
2017-10-31 本文已影响172人
zlcook
Index
- Graph Index:提高图查询顶点和边的速度。
- vertex-centric index:提高遍历图(从一个顶点到另一个顶点)的速度,尤其是遍历通过边连接的顶点。
Graph Indexes
- 提高了查询顶点和边的速度,没有索引则会进行全局一个一个匹配查询。
- 通过property key建立的索引查询vertex和edge
- 索引名称必须唯一
//建索引语句,提供索引名称、被索引的元素类型(Vertex.class、Edge.class)
JanusGraphManagement.buildIndex(String:indexName, Class:className)
- 配置文件中强制开启索引,不然就会不使用索引
force-index =true
-
在一个事务对新创建的属性建立索引会立即生效。
-
对于已经存在的属性创建索引需要执行 reindex procedure去将之前的元素(使用该属性的元素)加入到索引中,直到reindex procedure执行完成索引才会生效。所以建议索引在初始化schema时候创建。
-
分为:Composite Index索引和Mixed Index索引。
Composite Index
- 依赖存储后端,而不是索引后端
- 只支持对property key的等价查询,如果使用了谓词则不会其作用。
- 支持单属性和多属性的索引,对多属性索引,在查询时只有使用了多个属性才会使用该索引,如果只使用一个属性,则多属性索引不起作用。
- 支持Index Uniqueness(可选):即被索引的property key其值具有唯一性,如:name是唯一复合索引中的key,那么name=zhouliang的的值在全局中最多只能在顶点或边的name属性中出现一次。
- 在具有最终一致性的存储后端上如果要保证属性唯一性,索引的一致性约束就需要开启。
案例
- 创建索引byNameComposite、byNameAndAgeComposite
graph.tx().rollback() //Never create new indexes while a transaction is active
mgmt = graph.openManagement()
name = mgmt.getPropertyKey('name')
age = mgmt.getPropertyKey('age')
mgmt.buildIndex('byNameComposite', Vertex.class).addKey(name).buildCompositeIndex()
mgmt.buildIndex('byNameAndAgeComposite', Vertex.class).addKey(name).addKey(age).buildCompositeIndex()
mgmt.commit()
//Wait for the index to become available
mgmt.awaitGraphIndexStatus(graph, 'byNameComposite').call()
mgmt.awaitGraphIndexStatus(graph, 'byNameAndAgeComposite').call()
//Reindex the existing data
mgmt = graph.openManagement()
mgmt.updateIndex(mgmt.getGraphIndex("byNameComposite"), SchemaAction.REINDEX).get()
mgmt.updateIndex(mgmt.getGraphIndex("byNameAndAgeComposite"), SchemaAction.REINDEX).get()
mgmt.commit()
- g.V().has('name', 'hercules') 使用了byNameComposite索引
- g.V().has('age', 30).has('name', 'hercules') 使用了byNameAndAgeComposite索引
- g.V().has('age', 30) 不会使用byNameAndAgeComposite索引,必须使用多个属性
- g.V().has('name', 'hercules').has('age', inside(20, 50)) 使用byNameComposite而不是byNameAndAgeComposite,因为age不是等值查询。
Mixed Index
-
依赖索引后端进行查询,所以必须配置索引后端,而且JanusGraph可以支持多个索引后端,每个存储后端的名称在配置中必须唯一标识。
-
优点
- 比复合索引要灵活:多余多属性索引,查询时不需要指定所有属性也会使用索引、支持等值查询和其他查询
- 支持更多条件谓词
- 支持全文查询、范围查询、geo查询
- 可以配置是全文索引(默认):对属性值进行分词,查询时如果匹配的一个词就可以查询到。(全文搜索)
- 或配置成字符串索引:属性值作为整体进行匹配。具体:Index Parameters and Full-Text Search
- 可以为已存在的索引添加新的property key。(方法:addIndexKey)
-
缺点
- 对于等值查询比复合索引要慢。
- 不支持唯一索引。
-
在建立Mixed Index时需要指定索引后端名称,该名称是JanusGraph配置文件【index.*.backend】配置项中*号代表的值。如果要支持不同的索引后端,则在启动JanusGraph的配置中指定不同索引后端和名称。(即两个配置文件使用不同索引后端)
案例
- 创建名为nameAndAge的Mixed Index索引,并使用配置文件里名称为search的索引后端。
graph.tx().rollback() //Never create new indexes while a transaction is active
mgmt = graph.openManagement()
name = mgmt.getPropertyKey('name')
age = mgmt.getPropertyKey('age')
//age 默认也是Mapping.TEXT类型
mgmt.buildIndex('nameAndAge', Vertex.class).addKey(name,Mapping.TEXT.getParameter()).addKey(age).buildMixedIndex("search")
mgmt.commit()
//Wait for the index to become available
mgmt.awaitGraphIndexStatus(graph, 'nameAndAge').call()
//Reindex the existing data
mgmt = graph.openManagement()
mgmt.updateIndex(mgmt.getGraphIndex("nameAndAge"), SchemaAction.REINDEX).get()
mgmt.commit()
- 下面的查询都会使用mixed Index索引
//谓词,范围。因为是TEXT(全文索引)所以textContains谓词是可以的。
g.V().has('name', textContains('hercules')).has('age', inside(20, 50))
g.V().has('name', textContains('hercules'))
g.V().has('age', lt(50))
Adding Property Keys(for Mixed Index)
- 可以为已存在的mixed index添加新的属性key,那么在后续查询中就可以使用该条件。
- 如果新加的属性是新建的,那么index立即生效。
- 如果新加的属性已经在使用了,同样,需要执行 reindex procedure程序,将该属性之前的数据都加入到index中,reindex procedure执行完成后,该属性在索引中才可以使用。
- 案例代码
graph.tx().rollback() //Never create new indexes while a transaction is active
mgmt = graph.openManagement()
location = mgmt.makePropertyKey('location').dataType(Geoshape.class).make()
nameAndAge = mgmt.getGraphIndex('nameAndAge')
mgmt.addIndexKey(nameAndAge, location)
mgmt.commit()
//Previously created property keys already have the status ENABLED, but
//our newly created property key "location" needs to REGISTER so we wait for both statuses
mgmt.awaitGraphIndexStatus(graph, 'nameAndAge').status(REGISTERED, ENABLED).call()
//Reindex the existing data
mgmt = graph.openManagement()
mgmt.updateIndex(mgmt.getGraphIndex("nameAndAge"), SchemaAction.REINDEX).get()
mgmt.commit()
Mapping Parameters (for Mixed Index)
- 一个属性被添加到Mixed Index( 通过index builder 或者adddIndexKey方法),对于属性的值如何存储到索引后端,有一些列的参数可以配置。Refer to the mapping parameters overview for a complete list of parameter types supported by each indexing backend.
Label Constraint (for Graph Index)
- 只针对特定label的顶点或者边进行索引,可以在创建索引时添加indexOnly()方法来进行限制。
- 下面案例:只对针对那些有god标签的顶点进行name索引。(如果是Index Uniqueness同样适用)
name = mgmt.getPropertyKey('name')
god = mgmt.getVertexLabel('god')
mgmt.buildIndex('byNameAndLabel', Vertex.class).addKey(name).indexOnly(god).buildCompositeIndex()
mgmt.commit()
Ordering (for Graph Index)
- Composite Index不支持排序查询,其会将所有查询所有数据,并将满足的数据放入内存中进行排序。
- Mixed Index支持排序查询,但是查询的property key必须是mixed Index中存在的key,不然其会将所有结果到载入到内存中进行排序。
Composite和Mixed Indexes比较
-
- Use a composite index for exact match index retrievals. Composite indexes do not require configuring or operating an external index system and are often significantly faster than mixed indexes.
- As an exception, use a mixed index for exact matches when the number of distinct values for query constraint is relatively small or if one value is expected to be associated with many elements in the graph (i.e. in case of low selectivity).
- Use a mixed indexes for numeric range, full-text or geo-spatial indexing. Also, using a mixed index can speed up the order().by() queries.
Vertex-centric Indexes
-
针对特定类型(label)edge的property key进行索引。
-
前缀索引:即如果索引的属性字段包含多个,在查询时应该按照字段顺序进行查询。否则不会使用索引,类似于mysql的多属性索引,在查询时必须按照顺序指定。
-
使用索引案例
//使用图索引
h = g.V().has('name', 'hercules').next()
g.V(h).outE('battled').property('rating', 5.0) //Add some rating properties
//下面会使用Vertex-centric Indexes
g.V(h).outE('battled').has('rating', gt(3.0)).inV()
g.V(h).outE('battled').has('rating', 5.0).has('time', inside(10, 50)).inV()
g.V(h).outE('battled').has('time', inside(10, 50)).inV()
- 被索引的key必须指定明确的类型,即Object.class不会被索引。浮点类型要指定小数位。
- The property keys used in a vertex-centric index must have an explicitly defined data type (i.e. not Object.class) which supports a native sort order. If the data type are floating point numbers, JanusGraph’s custom Decimal or Precision data types must be used which have a fixed number of decimals.
rating = mgmt.makePropertyKey('rating').dataType(Double.class).make()
- 对于没有约束的查询,随着数据的增加会变慢。
Ordered Traversals
- 有序查询时,排序关键字及排序方向(升、降序)如果和index定义的相同会增加查询速度。