Neo4j/Cypher_LOCK_好还是坏?

Neo4j/Cypher _LOCK_ good or bad?

假设您有 (:User) 个节点,其中有 SubscribersCount 属性.

每次来自用户 User.SubscribersCount 的某人 subscribes/unsubscribes 应该相应地更新。 [:SUBSCRIBED] 关系也将 create/deleted 用于此类操作。

在这种情况下,为了更新计数器,您可以:

第一种方法会随着用户订阅者数量的增加而降级。

第二种方法呢?有什么缺点?

[更新(三次)]

为了开始讨论,这里有针对您的 2 个选项的 Cypher 查询示例。

  1. 根据需要计算关系计数(没有 SubscribersCount 属性):

    (a) 添加关系:

        MATCH (u:User {id:1234}), (v:User {id: 5678})
        CREATE (u)<-[:SUBSCRIBED]-(v);
    

    (b) 使用 SIZE 获取计数 [根据@NicoleWhite,只要使用的模式未指定标签,此 应该 在恒定时间内执行对于订阅者的节点并且 u 已经被缓存]:

        MATCH (u:User {id:1234})
        RETURN SIZE((u)<-[:SUBSCRIBED]-());
    

    (c) (已弃用) 使用 COUNT 获取计数 [neo4j 必须遍历该用户的所有关系(所有类型)]:

        MATCH (u:User {id:1234})
        RETURN COUNT((u)<-[:SUBSCRIBED]-());
    
  2. 在每个 User:

    上维护一个 SubscribersCount 属性

    (a) 添加一个关系 [同上,但多了一个 SET]:

        MATCH (u:User {id:1234}), (v:User {id: 5678})
        CREATE (u)<-[:SUBSCRIBED]-(v)
        SET u.SubscribersCount = u.SubscribersCount + 1;
    

    (b) GET 计数[常数时间复杂度]:

        MATCH (u:User {id:1234})
        RETURN u.SubscribersCount;
    

结论

假设 u 节点被缓存后,选项 1b 确实在恒定时间内执行,那么您应该始终使用选项 1a 添加 SUBSCRIBED 关系,并使用 1b 获取这种关系的计数。维护自己的计数可能会更慢。

但是,正如@drgraduss 提醒我们的那样,如果您需要按属性过滤关系或使用标签,那么选项 1b 将不会 运行 在常数时间内。

  • 一些例子:

    SIZE(()-[:SUBSCRIBED {prop:val}]->(u))
    SIZE((:label)-[:SUBSCRIBED]->(u))
    
  • 在这种情况下,选项 2 可能 更好,因为 2a 和 2b 运行 在常数时间内。