在 Neptune 中如何处理 Gremlin 查询 - Amazon Neptune
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

在 Neptune 中如何处理 Gremlin 查询

在 Amazon Neptune 中,可以通过一系列模式来表示更复杂的遍历,这些模式基于命名变量的定义创建关系,而命名变量可以在模式之间共享以创建联接。如以下示例所示。

问题:顶点 v1 有哪些两跳邻域?

Gremlin code: g.V(‘v1’).out('knows').out('knows').path() Pattern: (?1=<v1>, <knows>, ?2, ?) X Pattern(?2, <knows>, ?3, ?) The pattern produces a three-column relation (?1, ?2, ?3) like this: ?1 ?2 ?3 ================ v1 v2 v3 v1 v2 v4 v1 v5 v6

通过在两个模式之间共享 ?2 变量(在第一个模式的 O 位置和第二个模式的 S 位置),可以创建从一跳邻域到二跳邻域的联接。每个 Neptune 解都有三个命名变量的绑定,这些变量可用于重新创建 TinkerPopTraverser(包括路径信息)。

Gremlin 查询处理的第一步是将查询解析为 TinkerPop Traversal 对象,该对象由一系列步骤组成。 TinkerPop 这些步骤是开源 Apache TinkerPop 项目的一部分,既是逻辑运算符,也是物理运算符,在参考实现中构成 Gremlin 遍历。它们都用于表示查询模型。它们是可执行的运算符,可以根据其代表的运算符的语义生成解决方案。例如,.V()既由表示又由执行 TinkerPop GraphStep

由于这些 off-the-shelf TinkerPop 步骤是可执行的,因此这样的 TinkerPop Traversal 可以执行任何 Gremlin 查询并生成正确的答案。但是,当针对大型图表执行时, TinkerPop 步骤有时效率低下且速度很慢。Neptune 不使用这些步骤,而是尝试将该遍历转换为由模式组组成的声明形式(如前所述)。

当前,Neptune 的原生查询引擎仅支持部分 Gremlin 运算符(步骤)。因此,它尝试将尽可能多的步骤折叠为一个 NeptuneGraphQueryStep,其中包含已转换的所有步骤的声明性逻辑查询计划。理想情况下,所有步骤都将转换。但是,当遇到无法转换的步骤时,Neptune 会脱离原生执行,并将所有查询执行从该点推迟到这些步骤。 TinkerPop 它不会尝试穿插进行本机执行。

将步骤转换成逻辑查询计划后,Neptune 运行一系列查询优化器,以根据静态分析和估计基数来重写查询计划。优化器执行多种操作,例如根据范围计数对运算符进行重新排序、删除不必要或多余的运算符、重新排列筛选条件、将运算符推入不同的组等。

生成优化的查询计划后,Neptune 创建物理运算符的管道来执行查询。这包括从语句索引中读取数据、执行各种类型的联接、筛选、排序等。管道生成解流,然后将其转换回 TinkerPop Traverser 对象流。

查询结果的序列化

Amazon Neptune 目前依靠 TinkerPop 响应消息序列化器将查询结果(TinkerPop Traversers)转换为序列化数据,然后通过电线发送回客户端。这些序列化格式往往很冗长。

例如,要序列化 g.V().limit(1) 等顶点查询的结果,Neptune 查询引擎必须执行一次搜索来生成查询结果。但是,GraphSON 序列化程序将执行大量额外的搜索,才能将顶点打包为序列化格式。它必须执行一次搜索来获取标签,执行一次搜索来获取属性键,并对顶点的每个属性键执行一次搜索来获取每个键的所有值。

某些序列化格式效率更高,但是所有序列化格式都需要进行额外的搜索。此外, TinkerPop 序列化程序不会尽量避免重复搜索,这通常会导致不必要地重复许多搜索。

因此,在编写查询时,只询问所需的信息极为重要。例如,g.V().limit(1).id() 将仅返回顶点 ID,并消除所有其他序列化程序搜索。Neptune 中的 Gremlin profile API 允许您查看在查询执行和序列化期间进行了多少次搜索调用。