如何在OrientDB中有效地遍历许多顶点

时间:2019-06-03 09:31:12

标签: orientdb query-performance

我在orientdb中构建了一个树,该树在自下而上的方向上具有大量节点和边缘。我想收到那棵树的所有叶子(每片叶子都有@class LEAF),它们符合某个范围条件(例如val> 150和val <300):

示例:

       o
     /   \
    o     o 
   /    /  \ 
  o    o    o
 210  120   /\
          270 180

结果:210、180、270

到目前为止,我尝试使用以下查询:

SELECT FROM(TRAVERSE IN() FROM #123:123) WHERE value > 150 and value < 300

这在一些元素上运行良好,但是性能随着叶子数量的增加而下降。所以我的问题是:

  1. 这是在OrientDB中执行此操作的最有效方法,特别是如果我假设每个节点下有300000个叶子吗?
  2. 我从文档中知道,使用索引可以帮助提高范围查询的性能,但是在这种情况下会使用索引吗?我的第一个假设是否,因为东方先遍历然后过滤遍历的元素不是吗?

1 个答案:

答案 0 :(得分:0)

要提高性能,请尝试考虑查询应该执行的最少工作量,以找到正确的叶子:您要查找具有某些值的叶子>是某些树的一部分。

因此,您只想选择两个条件都成立的叶子。但是,除非您以某种方式为叶子提供信息,否则叶子不知道它们属于哪棵树。幸运的是,OrientDB允许您向边缘(或叶子本身)添加属性,从而使这一工作变得非常容易。

因此,在这种情况下,建议您将树的名称添加到该树的每个边缘。这样,每个叶子都会“通过关联”“知道”它属于哪棵树。

例如,让我们创建示例树:

CREATE CLASS Node EXTENDS V
CREATE PROPERTY Node.name INTEGER
CREATE VERTEX Node SET name = 1
CREATE VERTEX Node SET name = 2
CREATE VERTEX Node SET name = 3
CREATE VERTEX Node SET name = 4

CREATE CLASS LEAF EXTENDS V
CREATE PROPERTY LEAF.val FLOAT
CREATE VERTEX LEAF SET val = 210
CREATE VERTEX LEAF SET val = 120
CREATE VERTEX LEAF SET val = 270
CREATE VERTEX LEAF SET val = 180

CREATE CLASS C EXTENDS E
CREATE PROPERTY C.tree STRING
CREATE EDGE C FROM (SELECT * FROM Node WHERE name = 1) TO (SELECT * FROM Node WHERE name = 2) SET tree = 'example'
CREATE EDGE C FROM (SELECT * FROM Node WHERE name = 1) TO (SELECT * FROM Node WHERE name = 3) SET tree = 'example'
CREATE EDGE C FROM (SELECT * FROM Node WHERE name = 3) TO (SELECT * FROM Node WHERE name = 4) SET tree = 'example'
CREATE EDGE C FROM (SELECT * FROM Node WHERE name = 2) TO (SELECT * FROM LEAF WHERE val = 210) SET tree = 'example'
CREATE EDGE C FROM (SELECT * FROM Node WHERE name = 3) TO (SELECT * FROM LEAF WHERE val = 120) SET tree = 'example'
CREATE EDGE C FROM (SELECT * FROM Node WHERE name = 4) TO (SELECT * FROM LEAF WHERE val = 270) SET tree = 'example'
CREATE EDGE C FROM (SELECT * FROM Node WHERE name = 4) TO (SELECT * FROM LEAF WHERE val = 180) SET tree = 'example'

请注意EDGEC如何包含属性C.tree(字符串)。在NodesLEAFs之间创建边缘时,请为每个EDGE指定树的名称。在这种情况下,我向每个边缘添加了SET tree = 'example'

结果如下:

tree example

接下来,在LEAF.val上创建索引(以加快值搜索),并在C.tree上创建索引以快速识别每个叶子所属的树:

CREATE INDEX leafIndex ON LEAF (val) NOTUNIQUE
CREATE INDEX connectIndex ON C (tree) NOTUNIQUE

您现在可以在叶子上执行性能卓越的查询,如下所示:

SELECT * FROM LEAF WHERE inE('C').tree = ["example"] AND val > 150 and val < 300

此查询执行以下操作:

  1. 选择所有叶子...
  2. 具有类in的{​​{1}}边,并且C属性等于“ example”
  3. 并具有介于150和300之间的tree属性

此方法还避免了使用val,这比仅使用traverse更为昂贵。

结果正是您想要的:

query example

从查询说明中我们还可以看到优化引擎正在使用索引:

select

即使您有很多叶子,此查询也应该表现良好。

祝你好运!

PS。您还可以将树的名称添加到每个顶点(而不是边),这也是一种解决方案!但是在那种情况下,请记住当一片叶子是多棵树的一部分时会发生什么。