首页 > 解决方案 > 用于执行日期比较的简单 Neptune Gremlin 查询由于大连接而降级

问题描述

我们有一个包含客户和产品顶点的图表。对于给定的产品,我们想了解有多少在 DATE 之前注册的客户购买了该产品。我的查询看起来像

g.V('PRODUCT_GUID') // get product vertex
  .out('product-customer') // get all customers who ever bought this product
  .has('created_on', gte(datetime('2020-11-28T00:33:44.536Z'))) // see if the customer was created after a given date
  .count() // count the results

这个查询非常慢,所以我查看了海王星分析器,发现了一些奇怪的东西。下面是完整的分析器输出。忽略分析器中的经过时间。这是在多次尝试同一个查询之后,所以缓存是温暖的。在野外,可能需要 45 秒或更长时间。

*******************************************************
                Neptune Gremlin Profile
*******************************************************

Query String
==================
g.V('PRODUCT_GUID').out('product-customer').has('created_on', gte(datetime('2020-11-28T00:33:44.536Z'))).count()

Original Traversal
==================
[GraphStep(vertex,[PRODUCT_GUID]), VertexStep(OUT,[product-customer],vertex), HasStep([created_on.gte(Sat Nov 28 00:33:44 UTC 2020)]), CountGlobalStep]

Optimized Traversal
===================
Neptune steps:
[
    NeptuneCountGlobalStep {
        JoinGroupNode {
            PatternNode[(?1=<PRODUCT_GUID>, ?5=<product-customer>, ?3, ?6) . project ?1,?3 . IsEdgeIdFilter(?6) .], {estimatedCardinality=30586, expectedTotalOutput=30586, indexTime=0, joinTime=14, numSearches=1, actualTotalOutput=13424}
            PatternNode[(?3, <created_on>, ?7, ?) . project ask . CompareFilter(?7 >= Sat Nov 28 00:33:44 UTC 2020^^<DATETIME>) .], {estimatedCardinality=1285574, indexTime=10, joinTime=140, numSearches=13424}
        }, annotations={path=[Vertex(?1):GraphStep, Vertex(?3):VertexStep], joinStats=true, optimizationTime=0, maxVarId=8, executionTime=165}
    }
]

Physical Pipeline
=================
NeptuneCountGlobalStep
    |-- StartOp
    |-- JoinGroupOp
        |-- SpoolerOp(1000)
        |-- DynamicJoinOp(PatternNode[(?1=<PRODUCT_GUID>, ?5=<product-customer>, ?3, ?6) . project ?1,?3 . IsEdgeIdFilter(?6) .], {estimatedCardinality=30586, expectedTotalOutput=30586})
        |-- SpoolerOp(1000)
        |-- DynamicJoinOp(PatternNode[(?3, <created_on>, ?7, ?) . project ask . CompareFilter(?7 >= Sat Nov 28 00:33:44 UTC 2020^^<DATETIME>) .], {estimatedCardinality=1285574})

Runtime (ms)
============
Query Execution: 164.996

Traversal Metrics
=================
Step                                                               Count  Traversers       Time (ms)    % Dur
-------------------------------------------------------------------------------------------------------------
NeptuneCountGlobalStep                                                 1           1         164.919   100.00
                                            >TOTAL                     -           -         164.919        -

Predicates
==========
# of predicates: 131

Results
=======
Count: 1
Output: [22]


Index Operations
================
Query execution:
    # of statement index ops: 13425
    # of unique statement index ops: 13425
    Duplication ratio: 1.0
    # of terms materialized: 0

尤其

DynamicJoinOp(PatternNode[(?3, <created_on>, ?7, ?) . project ask . CompareFilter(?7 >= Sat Nov 28 00:33:44 UTC 2020^^) .], {estimatedCardinality=1285574})

这条线让我吃惊。我读这篇文章的方式是海王星忽略了来自“.out('product-customer')”的顶点来满足“.has('created_on'...)”的要求,而是加入每一个具有 created_on 属性的单个客户顶点。

我本来预计基数只是从产品中获得优势的客户数量,而不是每个客户。

我想知道是否有办法只对来自“out('product-customer')”步骤的客户进行比较。

标签: amazon-web-servicesgremlinamazon-neptune

解决方案


海王星实际上必须解决第一个模式,

(?1=<PRODUCT_GUID>, ?5=<product-customer>, ?3, ?6)

在它解决第二个之前,

(?3, <created_on>, ?7, ?)

每个四边形模式都是由至少两个字段绑定的索引查找。因此,第一次查找使用 Neptune 中的 SPOG 索引,该索引由 Subject(ID)和 Predicate(边缘标签)绑定。这将返回一组对象(产品-客户边另一端的顶点的顶点 ID)并通过?3变量引用它们以用于下一个模式。

在下一个模式中,这些顶点 ID ( ?3) 与谓词(created-on 的属性键)绑定以评估日期范围的条件。因为这是一个条件评估,所以?3必须评估集合中的每个顶点(必须读取每个顶点上的每个“created-on”属性)。


推荐阅读