【问题标题】:Copying a property from a node is slow with a lot of nodes有很多节点,从节点复制属性很慢
【发布时间】:2015-08-14 17:15:33
【问题描述】:

我正在迁移标记节点中的一些属性,查询性能很差。

旧属性是 callerRef,新属性是 code。有 17m 节点需要更新,我想批量处理。实体上没有 code 属性表示它尚未升级。

profile match (e:Entity) where not has(e.code) with e limit 1000000 set e.key = e.callerKeyRef, e.code = e.callerRef;

实体标签中有一个索引,用于代码。

schema -l :Entity
Indexes
  ON :Entity(code) ONLINE
No constraints

堆分配了 8gbs 运行 Neo4j 2.2.4。如果我正确地阅读了计划,问题是即使指定了限制子句,标签中的所有节点都被命中。我原以为在请求限制的无序查询中,在满足限制条件后处理将停止。

+-------------------+
| No data returned. |
+-------------------+
Properties set: 2000000
870891 ms

Compiler CYPHER 2.2

+-------------+----------+----------+-------------+--------------------------+
|    Operator |     Rows |   DbHits | Identifiers |                    Other |
+-------------+----------+----------+-------------+--------------------------+
| EmptyResult |        0 |        0 |             |                          |
| UpdateGraph |  1000000 |  6000000 |           e | PropertySet; PropertySet |
|       Eager |  1000000 |        0 |           e |                          |
|       Slice |  1000000 |        0 |           e |             {  AUTOINT0} |
|      Filter |  1000000 | 16990200 |           e |     NOT(hasProp(e.code)) |
| NodeByLabel | 16990200 | 16990201 |           e |                  :Entity |
+-------------+----------+----------+-------------+--------------------------+

Total database accesses: 39980401

我是否遗漏了一些明显的东西? TIA

【问题讨论】:

标签: neo4j cypher


【解决方案1】:

仅支持 =IN 的索引(它们基本上是相同的,因为 Cypher 编译器转换了 IN 中的所有 = 操作)。

Neo4j 是无模式数据库。因此,如果没有属性 - 就没有索引数据。这就是它需要扫描所有节点的原因。

我的建议:

  • 第一步:将code 属性添加到所有必要的节点,并带有一些默认的“假”值
  • 使用node.code = "none" where 子句进行更新

【讨论】:

    【解决方案2】:

    首先为所有尚未迁移的节点分配一个新标签(例如 ToDo)可能会更快:

    MATCH (e:Entity)
    WHERE NOT HAS (e.code)
    SET e:ToDo;
    

    然后,您可以一次迭代匹配 1000000 个(或其他)ToDo 节点,在迁移每个节点后删除 ToDo 标签:

    MATCH (e:ToDo)
    WITH e
    LIMIT 1000000
    SET e.key = e.callerKeyRef, e.code = e.callerRef
    REMOVE e:ToDo;
    

    【讨论】:

    • 尽管我认为这会起作用,但仍然会扫描 1700 万个节点在应用过滤器之前。您必须从最后一个条目到第一个条目阅读上面的配置文件。将标签应用于 1700 万个节点,而不对工作进行批处理(堆/死锁)。批处理需要过滤——我们又回到了扫描问题。如果交互式运行,那么批量更新意味着扫描会越来越少。在第一次查询有帮助后缓存节点有帮助,但这意味着您可以在循环中运行 neo4j-shell -c 而不会导致第一次加载 o/head
    • 如果这种方法按预期工作,它确实会在标签设置步骤中访问所有 1700 万个节点(但将此步骤分成几个较小的步骤可能每次都访问所有 1700 万个节点,所以它一次完成这一切可能会更快)。但是,我提出的每一个迭代 100 万节点的步骤一次只能访问 100 万个节点,而不是全部 1700 万个。请使用个人资料,如果这些数字看起来很有希望,请告诉我们。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-15
    • 1970-01-01
    • 2023-04-09
    相关资源
    最近更新 更多