Gremlin查询中将低开销步骤置于高开销步骤前是否为有效优化?
Gremlin过滤步骤执行顺序通用解答
基础执行逻辑
从Apache TinkerPop的官方规范定义来看,Gremlin查询的步骤默认会按照编写顺序组成执行流水线,在没有被对应图数据库的查询优化器重排序的前提下,步骤会严格按照你编写的顺序执行。你提到的「低开销过滤步骤前置,提前淘汰大部分不符合条件的顶点,降低后续高开销步骤的迭代次数」的优化逻辑,在绝大多数Gremlin实现场景下都是成立的。
查询优化器对顺序的影响
不同图数据库的实现确实会有差异,部分支持高级查询优化的数据库会自动做谓词下推、过滤步骤重排序的操作,会自动把开销更低、过滤性更强的步骤调整到更靠前的位置执行,不受编写顺序的影响,但有两个通用规则可以参考:
- 只有优化器可以明确识别开销的步骤才会被重排序,比如基于索引的
has('属性名', '属性值')这类标准步骤的开销很容易被评估,会被优化器自动调整顺序;但复杂的自定义where()闭包、跨点边关联判断、带自定义函数的过滤步骤,优化器大多无法准确评估其开销,不会随意调整顺序,会严格按照编写位置执行。 - 没有内置高级查询优化器的图数据库(比如轻量级实现、仅基于TinkerPop默认层封装的数据库)完全不会做步骤重排序,编写顺序就是最终的执行顺序,这种场景下主动前置低开销步骤的收益会非常明显。
通用优化建议
哪怕你不确定当前使用的图数据库是否支持步骤重排序,也建议你主动把低开销、高过滤性的过滤步骤写在最前面,原因如下:
- 对于不会做步骤重排序的数据库,这是必要的优化操作,可以直接降低后续所有步骤的计算量。
- 对于会做步骤重排序的数据库,你的编写顺序不会影响优化效果,优化器识别到更优的执行顺序后会自动调整,不会产生额外的性能损耗。
举个实际的场景示例:你有一个能走属性索引的低开销过滤has('age', gt(18)),可以直接筛掉90%的无效顶点,还有一个需要遍历出边做计数判断的高开销过滤where(out('follow').count().is(gt(10))),不管你用什么类型的Gremlin数据库,把has步骤放在where步骤前面都是最优的写法。
内容的提问来源于stack exchange,提问作者fermmm
相关产品推荐
相关产品推荐

