orientdb - OrientDB中如何高效遍历多个顶点
问题描述
我在 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
这适用于一些元素,但性能会随着叶子数量的增加而下降。所以我的问题是:
- 这是在 OrientDB 中执行此操作的最有效方法,特别是如果我假设每个节点下有 300000 个叶子?
- 我从文档中知道,使用索引可以帮助提高范围查询的性能,但是在这种情况下会使用索引吗?我的第一个假设是否定的,因为 orient 首先遍历然后过滤遍历的元素,不是吗?
解决方案
为了提高性能,试着考虑查询应该做的最小工作量来找到正确的叶子:你想找到属于某个树的具有特定值的叶子。
因此,您只想选择这两个条件都为真的叶子。但是,叶子不知道它们属于哪棵树,除非您以某种方式向它们提供该信息。幸运的是,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'
注意EDGE
类如何C
包含属性C.tree
(字符串)。Nodes
在和之间创建边时LEAFs
,将树的名称赋予每个EDGE
。在这种情况下,我添加SET 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
此查询执行以下操作:
- 选择所有叶子...
- 具有属性等于“示例”的
in
类边缘C
tree
- 并且拥有
val
150到300之间的房产
这种方法也避免了使用traverse
,这比使用更昂贵select
。
结果正是您想要的:
从查询解释中我们也可以看出优化引擎正在使用索引:
+ FETCH FROM INDEX leafIndex
val > 150 and val < 300
+ EXTRACT VALUE FROM INDEX ENTRY
filtering clusters [273,274,275,276,277,278,279,280]
+ FILTER ITEMS WHERE
inE('C').tree = ["example"]
+ FILTER ITEMS BY CLASS
LEAF
+ CALCULATE PROJECTIONS
*
这个查询应该执行得很好,即使你有很多叶子。
祝你好运!
PS。您还可以将树的名称添加到每个顶点(而不是边),这也是一种解决方案!但在这种情况下,请注意当一片叶子是多棵树的一部分时会发生什么。
推荐阅读
- html - shiny::showModal 不适用于 Shinymanager
- java - 如何在 ArrayList 为真或在 Kotlin 中完成后显示 AlertDialog?
- python-3.x - python3位移超过64次
- android - Markdown 编辑器和预览在 Android Studio 中不起作用?
- android - 如果 Regex 电话号码是有效的 Android,则启用设置按钮
- ruby-on-rails - Nginx 如何在请求非摘要 favicon.ico 时提供摘要 favicon 文件
- javascript - beforeinstallprompt 未在应用内浏览器中触发
- python - 使用 Tasker 在 docker-compose 中运行 Python 脚本
- antd - 在 Antd 中使用甘特图
- android - 在 textview (Kotlin) 中显示本地日期