首页 > 解决方案 > 添加许多节点属性时在NEO4J中加载数据很慢

问题描述

我正在尝试可视化防火墙日志数据。首先,我使用的是 Windows 应用程序防火墙日志。

我正在使用 LOAD CSV WITH HEADERS。当我只有有限数量的关系属性时,它运行良好,但只要我向关系中添加一个属性,它就会变慢,需要 30 分钟以上的时间来处理。

下面的示例快速加载:

        $queries['statements'] = @()

        $query = "LOAD CSV WITH HEADERS FROM 'file:///data/go_output/$($uuid)_send_data.csv' AS row
        MERGE (from:ipobj {ip: row.srcip, ipversion: row.srcipver, internal: row.srcipinternal})
        MERGE (to:ipobj {ip: row.dstip, ipversion: row.dstipver, internal: row.dstipinternal})
        MERGE (from)-[datatransfer:SENT {date: row.date, type: row.action, size: row.size}]->(to)"
        $queries['statements'] += [ordered]@{'statement'="$($query)"}

        $retval = $queries| ConvertTo-Json

        $url = "http://127.0.0.1:7474"
        $credPair = "neo4j:test"
        $encodedCredentials = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($credPair))
        $headers = @{"Authorization"="Basic $encodedCredentials"; "Accept"="application/json; charset=UTF-8";"Content-Type"="application/json"}

        $response = Invoke-WebRequest -Uri "$($url)/db/data/transaction/commit" -Method Post -Headers $headers -Body $($retval)
        $response.content

下面的示例需要 15 分钟来处理:

        $queries = @{}
        $queries['statements'] = @()

        $query = "LOAD CSV WITH HEADERS FROM 'file:///data/go_output/$($uuid)_send_data.csv' AS row
        MERGE (from:ipobj {ip: row.srcip, ipversion: row.srcipver, internal: row.srcipinternal})
        MERGE (to:ipobj {ip: row.dstip, ipversion: row.dstipver, internal: row.dstipinternal})
        MERGE (from)-[datatransfer:SENT {date: row.date, type: row.action, size: row.size, srcport: row.srcport, dstport: row.dstport}]->(to)"
        $queries['statements'] += [ordered]@{'statement'="$($query)"}

        $retval = $queries| ConvertTo-Json

        $url = "http://127.0.0.1:7474"
        $credPair = "neo4j:test"
        $encodedCredentials = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($credPair))
        $headers = @{"Authorization"="Basic $encodedCredentials"; "Accept"="application/json; charset=UTF-8";"Content-Type"="application/json"}

        $response = Invoke-WebRequest -Uri "$($url)/db/data/transaction/commit" -Method Post -Headers $headers -Body $($retval)
        $response.content

NEO4j 抱怨一个急切的操作符,但只加载了 find 的 3 个属性。

帮助?我不知道为什么会这样。我检查了查询计划并进行了一系列故障排除,但不知道为什么会这样。为避免这篇文章太长,我不打算提出疑难解答,但请随时询问或告诉我我做错了什么!

请注意,我正在加载的文件或多或少是标准问题 Windows 防火墙 (pfirewall.log) 文件,具有以下修改:

标签: neo4j

解决方案


Eager 运算符用于保留 Cypher 语义,但由于其在处理大型数据集(例如使用 LOAD CSV)时的后果而成为一个主要问题。有计划的更改来缓解这种情况,但这是为了未来。

更多信息: https ://community.neo4j.com/t/cypher-sleuthing-the-eager-operator/10730

对于变通方法,我们可以在查询中做一些扭曲,或者更容易,将其分为 3 次传递:一次合并from节点,一次合并to节点,第三次匹配两者,然后合并它们之间的关系。

编辑:

感谢您提供的查询计划,我们可以看到您的 MERGE 没有索引支持,这就是我们在计划中看到 NodeByLabelScans 的原因。每行,对于两个节点中的每一个,都会检查和过滤每个 :ipobj 节点,这不会有效。

您需要一个索引来快速完成此操作。

什么唯一标识 :ipobj 节点?如果它只是ip属性,那么创建一个唯一的约束。如果它是属性的组合,则创建一个节点键约束,或者至少在给定属性上创建一个索引。

我关于解决 Eager 问题的评论仍然有效,但是您需要使用索引或约束来支持 MATCH 和 MERGE(尤其是在执行加载时!)以使其高效。


推荐阅读