Gremlin:找到两个顶点之间的边的有效方法是什么?
Gremlin: What's an efficient way of finding an edge between two vertices?
很明显,在两个顶点之间找到一条边的直接方法是:
graph.traversal().V(outVertex).bothE(edgeLabel).filter(__.otherV().is(inVertex))
我觉得 filter
步骤必须遍历所有边缘,这对于具有很多边缘的某些应用程序来说非常慢。
另一种方式可能是:
traversal = graph.traversal()
.V(outVertex)
.bothE(edgeLabel)
.as("x")
.otherV()
.is(outVertex) // uses index?
.select("x");
我假设第二种方法会更快,因为它将使用 ID 索引,这将使其比第一种方法更快。
哪个更快更高效(在 IO 方面)?
我使用的是 Titan,因此您也可以针对 Titan 进行回答。
编辑
就时间而言,第一种方法似乎更快(顶点的边为 20k b
gremlin> clock(100000){g.V(b).bothE().filter(otherV().is(a))}
==>0.0016451789999999999
gremlin> clock(100000){g.V(b).bothE().as("x").otherV().is(a).select("x")}
==>0.0018231140399999999
IO怎么样?
我希望第一个查询会更快。但是,有几件事:
- None 的查询是最佳的,因为它们都启用了路径计算。如果需要双向查找连接,那就用2个查询(下面我会举个例子)
- 当你使用
clock()
时,一定要iterate()
你的遍历,否则你只会测量什么都不做需要多长时间。
这些是我用来在两个方向上查找边缘的查询:
g.V(a).outE(edgeLabel).filter(inV().is(b))
g.V(b).outE(edgeLabel).filter(inV().is(a))
如果您希望最多获得一条边:
edge = g.V(a).outE(edgeLabel).filter(inV().is(b)).tryNext().orElseGet {
g.V(b).outE(edgeLabel).filter(inV().is(a)).tryNext()
}
这样你就可以摆脱路径计算。这些查询的执行方式在很大程度上取决于底层图形数据库。 Titan 的查询优化器可以识别该查询模式,并且应该 return 几乎没有时间就得到结果。
现在,如果您想测量运行时间,请执行以下操作:
clock(100) {
g.V(a).outE(edgeLabel).filter(inV().is(b)).iterate()
g.V(b).outE(edgeLabel).filter(inV().is(a)).iterate()
}
如果不知道顶点 ID,另一种解决方案可能是
g.V().has('propertykey','value1').outE('thatlabel').as('e').inV().has('propertykey','value2').select('e')
这也只是单向的,因此需要为相反方向重新制定查询。
很明显,在两个顶点之间找到一条边的直接方法是:
graph.traversal().V(outVertex).bothE(edgeLabel).filter(__.otherV().is(inVertex))
我觉得 filter
步骤必须遍历所有边缘,这对于具有很多边缘的某些应用程序来说非常慢。
另一种方式可能是:
traversal = graph.traversal()
.V(outVertex)
.bothE(edgeLabel)
.as("x")
.otherV()
.is(outVertex) // uses index?
.select("x");
我假设第二种方法会更快,因为它将使用 ID 索引,这将使其比第一种方法更快。
哪个更快更高效(在 IO 方面)?
我使用的是 Titan,因此您也可以针对 Titan 进行回答。
编辑
就时间而言,第一种方法似乎更快(顶点的边为 20k b
gremlin> clock(100000){g.V(b).bothE().filter(otherV().is(a))}
==>0.0016451789999999999
gremlin> clock(100000){g.V(b).bothE().as("x").otherV().is(a).select("x")}
==>0.0018231140399999999
IO怎么样?
我希望第一个查询会更快。但是,有几件事:
- None 的查询是最佳的,因为它们都启用了路径计算。如果需要双向查找连接,那就用2个查询(下面我会举个例子)
- 当你使用
clock()
时,一定要iterate()
你的遍历,否则你只会测量什么都不做需要多长时间。
这些是我用来在两个方向上查找边缘的查询:
g.V(a).outE(edgeLabel).filter(inV().is(b))
g.V(b).outE(edgeLabel).filter(inV().is(a))
如果您希望最多获得一条边:
edge = g.V(a).outE(edgeLabel).filter(inV().is(b)).tryNext().orElseGet {
g.V(b).outE(edgeLabel).filter(inV().is(a)).tryNext()
}
这样你就可以摆脱路径计算。这些查询的执行方式在很大程度上取决于底层图形数据库。 Titan 的查询优化器可以识别该查询模式,并且应该 return 几乎没有时间就得到结果。
现在,如果您想测量运行时间,请执行以下操作:
clock(100) {
g.V(a).outE(edgeLabel).filter(inV().is(b)).iterate()
g.V(b).outE(edgeLabel).filter(inV().is(a)).iterate()
}
如果不知道顶点 ID,另一种解决方案可能是
g.V().has('propertykey','value1').outE('thatlabel').as('e').inV().has('propertykey','value2').select('e')
这也只是单向的,因此需要为相反方向重新制定查询。