neo4j - 添加许多节点属性时在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) 文件,具有以下修改:
- 空格分隔符已更改为逗号
- 注释行已被删除并仅替换为标题
- 包含破折号的标题列名称,破折号已被删除(src-port 变为 srcport 等)
- 我确实添加了一个 ipversion 列(ipv4 与 ipv6)和一个 srcipinternal 布尔列,如 :ipobj 节点合并/创建中所示,但这些不是明确需要的。这些只是我以后做一些分析的东西。
- 实际上,我做了一些预处理,将文件拆分为 SEND/RECEIVED/FORWARD/UNKOWN 操作类型,以使下面的处理更容易,这就是为什么文件被称为 uuid_send_data.csv 的原因。
解决方案
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(尤其是在执行加载时!)以使其高效。
推荐阅读
- python - 将转换应用于所有列的最佳方法 - Pyspark 数据框
- r - 在 R 中用 gg.gap 断轴
- json - Python 3.6+ 如何在 while 循环中立即创建 json 转储文件。它仅在 while 循环终止后添加
- python - 如何使用 Python 检测计算机安装了多少内存?
- javascript - React JS:组件未与自定义路由组件一起显示?
- python - VSCode Pylance 更改了文本颜色
- java - 如何在 javafx 阶段设置背景图像
- excel - 更改工作表中随机单元格的颜色
- java - 在使用“gradle jar”创建 jar 之前是否应该“gradle clean”?
- xml - 如何在固定结构中解组动态 XML?