关于nebula:Nebula-Graph-源码解读系列-|-Vol06-MATCH-中变长-Pattern-的实现

23次阅读

共计 2616 个字符,预计需要花费 7 分钟才能阅读完成。

目录

  • 问题剖析

    • 定长 Pattern
    • 变长 Pattern 与变长 Pattern 的组合
  • 执行打算

    • 拓展一步
    • 拓展多步
    • 保留门路
    • 变长拼接
  • 总结

MATCH 作为 openCypher 语言的外围,通过简洁的 Pattern 模式,能够让用户不便地表白图库中的关联关系。变长模式又是 Pattern 中用来形容门路的一种罕用模式,对变长模式的反对是 Nebula 兼容 openCypher MATCH 性能的第一步。

由之前的系列文章能够理解到,Nebula 的执行打算是由许多的物理算子组成,每个算子都负责执行特有的计算逻辑,在 MATCH 的实现中也会波及前述文章中的这些算子,比方 GetNeighbors、GetVertices、Join、Project、Filter、Loop 等等。因为 Nebula 的执行打算不同于关系数据库中的树状构造,在执行的流程上其实是一个有环的图。如何把 MATCH 中的变长 Pattern 变成 Nebula 的物理打算是 Planner 要解决的问题的重点。以下便简略介绍一下在 Nebula 中解决变长 Pattern 问题的思路。

问题剖析

定长 Pattern

在应用 MATCH 语句时,定长 Pattern 也是比拟罕用的查问模式。如果把定长 Pattern 了解成向外拓展 X 步的变长 Pattern,认为其是后者的一种特例,那么定长和变长 Pattern 的实现便能够对立起来,如下所示:

// 定长 Pattern MATCH (v)-[e]-(v2)
// 变长 Pattern MATCH (v)-[e*1..1]-(v2)

上述示例中的区别就是变量 e 的类型,定长时 e 示意的是一条边,而变长时 e 示意的是长度为 1 的边列表。

变长 Pattern 与变长 Pattern 的组合

在 openCypher 的 MATCH 语法里,Pattern 能够灵便的组合以表白简单门路。如下所示,变长 Pattern 再接变长 Pattern:

MATCH (v)-[e*1..3]-(v2)-[ee*2..4]-(v3)

上述的过程能够是个一直延长的过程,通过变长定长模式的不同排列,能够组合出非常复杂的门路。所以咱们必须找到一种生成 plan 的模式能力不便的递归迭代整个过程。其中须要思考如下的因素:

  1. 前面变长 Pattern 的门路依赖后面所有变长门路;
  2. 变长 Pattern 前面的所有的符号(或者变量)示意的后果是“变动”的;
  3. 每一步在往外拓展之前须要对终点进行去重;

咱们能够留神到,如果能够生成 Pattern 中 ()-[:like*m..n]- 的局部的执行打算,那么前面持续进行组合迭代就变得有迹可循,如下所示:

()-[:like*m..n]- ()-[:like*k..l]- ()
 \____________/   \____________/   \_/
    Pattern1         Pattern2       Pattern3

执行打算

上面便剖析模式中 ()-[:like*m..n]- 的局部,查看其如何转换成 Nebula 的物理执行打算的。下面模式形容的意思是向外拓展 m 到 n 步,在 Nebula 中向外拓展一步是通过 GetNeighbors 算子实现的。如果要向外拓展多步,须要一直在上一步拓展的根底上再调用 GetNeighbors 算子,将每次获取的点边数据首尾连贯就会拼接成一个门路(path)。尽管用户最初须要的只是 m 到 n 步的门路,然而在执行的过程中仍然须要从第 1 步开始拓展直到第 n 步。并且每步拓展过程中的门路后果都须要保留下来,以便输入或者给下一步应用。最初只有拿出长度在区间 m 到 n 步之间的门路即可。

拓展一步

先来看看走一步的打算是什么样子,因为 Nebula 数据存储的形式为终点和出边搁置在一起,所以获取终点和出边的数据是不须要跨 partition 的。然而边的起点数据个别是跨 partition 的,须要独自通过 GetVertices 接口来获取点的属性。除此之外,在向外拓展之前,最好要把拓展的终点数据进行去重,防止 storage 反复扫描。所以走一步的执行打算如下图所示:

拓展多步

拓展多步的过程其实就是将上述的过程反复,然而咱们会留神到 GetNeighbors 能够获取终点的属性,所以在拓展下一步时,是能够省掉一步 GetVertices 操作。拓展两步的执行打算就变为:

保留门路

因为最初可能须要返回每一步拓展的门路,所以在上述拓展过程中,还须要将所有的门路进行保留。连贯两步之间的门路能够通过 join 算子实现。同时因为模式 ()-[e:like*m..n]- 的返回后果中 e 示意的是一列数据(边的 list),所以下面每步拓展门路须要通过 union 的形式进行后果集的合并。执行打算进一步演变为:

变长拼接

由下面的过程便能够生成模式  ()-[e:like*m..n]- 的物理打算,当多个相似模式做拼接时,就是再把上述的过程进行迭代。不过在进行模式迭代之前,还须要对下面打算失去的后果进行过滤,因为咱们冀望是失去 m 到 n 步的后果,下面的数据集中蕴含了从第 1 步到第 n 步的所有后果,通过对门路的长度做个简略的筛选即可。变长模式拼接之后的打算变为:

通过上述一步步的合成,咱们终于失去了最后 MATCH 语句冀望的执行打算,能够看到在把一个简单模式转换成底层的拓展接口时还是颇费功夫。当然下面的打算能够做些优化,比方把多步拓展的过程应用 Loop 算子进行封装,复用一步拓展的 sub-plan,这里不再具体开展。感兴趣的用户能够参考 nebula 源码实现。

总结

上述过程演示了一个变长 Pattern 的 MATCH 语句的执行打算生成过程,置信大家这时会有这样一个纳闷,为什么根本的一些门路拓展在 Nebula 中会生成这么简单的执行打算?比照 Neo4j 的实现,几个算子即可实现雷同的工作,在这里会变成繁琐的 DAG 呢?

这个问题的实质起因是 Nebula 的算子更靠近底层的接口,短少一些更下层的图操作语义上的形象。算子力度太细,就会导致下层的优化等实现须要思考太多的细节。前面会对执行算子进一步的梳理,来逐渐的欠缺 MATCH 性能和晋升性能。

《开源分布式图数据库 Nebula Graph 齐全指南》,又名:Nebula 小书,外面具体记录了图数据库以及图数据库 Nebula Graph 的知识点以及具体的用法,浏览传送门:https://docs.nebula-graph.com.cn/site/pdf/NebulaGraph-book.pdf

交换图数据库技术?退出 Nebula 交换群请先填写下你的 Nebula 名片,Nebula 小助手会拉你进群~~

正文完
 0