最优的OrientDB SQL查询模拟双方都有条件的连接

时间:2015-08-10 09:40:06

标签: sql orientdb graph-databases nosql

我有一个顶点类“Bucket”和一些名称不重要的顶点类。

我有一个名为“containedIn”的边缘。

我希望获得最佳的sql查询(在性能方面)以获取给定存储桶中包含的所有顶点。必须可以添加条件来过滤顶点。在关系数据库中,这将通过简单的连接完成。

第一次尝试。这会返回预期的顶点,但我想知道是否有更好的解决方案(可能试图避免使用嵌套选择?)。

SELECT FROM 
 (SELECT expand(set(in("containedIn"))) 
  FROM Bucket 
  WHERE @rid = #5:1 ) 
WHERE @rid > #10:0  
ORDER BY @rid  
LIMIT 10000

我也尝试过这个查询(仅限于轻量级=假模式),但我没有得到预期的结果。 ORDER BY使得它甚至不能编译,删除查询的子句但返回的结果与我的期望不同。

SELECT expand(inV()) 
FROM containedIn 
WHERE outV("Bucket").@rid = #5:1 and inV().@rid > #10:0 
ORDER BY inV().@rid 
LIMIT 10000

1 个答案:

答案 0 :(得分:3)

仅供参考 - 在OrientDB Studio网络应用程序中,有一个“解释”按钮,显示有关查询的性能信息。这是一个很好的工具,我在下面使用过。 java中可能提供相同的信息,但我没有使用java接口。

我已经做了一些自己的测试,看起来你的原始查询非常好。你唯一不需要的是set()函数。

通常我希望WHERE子句迭代'源列表'中的每条记录。因此,最好使您的“源列表”尽可能小。我稍后会回到这一点。

我还注意到您正在使用文档中推荐的RID-LIMIT分页方法,这很好。我将从以下查询中排除限制,因为它隐藏了一些查询的错误。

似乎OrientDB有一些快捷方式,我对SELECT FROM #1:1SELECT FROM V where @rid = #1:1的测试显示了始终处于同一个球场所需的时间。使用解释工具,我可以看到documentReads = 1。

我有一个数据库,在~700个“状态”(集群#41)中有~32000个“城市”(集群#42),与称为“区域”的轻量级边缘链接。我用它来进行以下查询...

SELECT FROM (SELECT expand(in('Region')) FROM #41:1) WHERE @rid > #42:1800 ORDER BY @rid 这与你的问题相同。它返回1538条记录,解释工具显示1633 documentReads,因此这看起来像一个有效的查询。这是非常直接的,因为你跟随'1真正来源'的边缘。

SELECT FROM City WHERE out_Region.@rid = #41:1 and @rid > #42:1800 ORDER BY @rid 这类似于您的第二个查询,但适合轻量级边缘。它返回与上面相同数量的记录(1538),但documentReads最多为30390!这是因为WHERE子句,因为它几乎读取每个城市记录,然后读取状态记录,并检查它的摆脱。因此,它可能也会加载每个州的记录(假设每个州的记录都与城市记录相关联)。这个查询不够直接。

你的第二个查询会遇到类似的问题(如果你的语法正确),因为它会读取每个'containedIn'边缘,然后每个桶链接到那些边缘(所以可能是每个桶),然后读取并返回正确的记录。这是很多阅读!

你问“可能试图避免使用嵌套的SELECT?”。当您执行SELECT in('Region') FROM #41:1时,您会得到一个rids列表。过滤这些rid是有意义的,然后在缩短的列表上使用expand()。这样,只会通过expand()读取相关记录。如果OrientDB不聪明,查询SELECT expand(in('Region')) FROM #41:1可能正在读取所有记录,但只返回一小部分(即如果查询找到如上所述的1538条记录,但限制为100,那么1438读取没必要)。看来OrientDB的开发人员已经考虑过了这一点,因为查询SELECT FROM (SELECT expand(in('Region')) FROM #41:1) limit 100只能完成100个documentReads。

但是,SELECT FROM (SELECT expand(in('Region')) FROM #41:1) WHERE @rid <= #42:1800返回了95条记录,SELECT FROM (SELECT expand(in('Region')) FROM #41:1) WHERE @rid > #42:1800 LIMIT 100执行了195条文档读取。更糟糕的是,SELECT FROM (SELECT expand(in('Region')) FROM #41:1) WHERE @rid > #42:1800 ORDER BY @rid LIMIT 100执行完整的1633 documentReads(我认为ORDER BY子句有错)。因此可能存在优化,因为在运行expand()函数之前可以从列表中对rid进行排序和过滤,但我无法想到如何在查询中执行此操作。这可能是开发人员需要解决的问题。