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

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

在 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 解决方案都具有三个命名变量的绑定,可用于重新创建TinkerPop Traverser(包括路径信息)。

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

由于这些现成的 TinkerPop 步骤是可执行的,因此这样的 TinkerPop 遍历可以执行任何 Gremlin 查询并生成正确的答案。但是,当针对大型图执行时,TinkerPop 步骤有时会非常低效且缓慢。如前所述,Neptune 尝试将其转换为由模式组组成的声明形式,而是尝试将其转换为由模式组成的声明形式。

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

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

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

查询结果的序列化

当前,Amazon Neptune 依靠 TinkerPop 响应消息序列化程序将查询结果 (TinkerPop 遍历) 转换为序列化的数据,以通过线路将其发送回客户端。这些序列化格式往往很冗长。

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

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

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