数据模型如何影响CYPHER的neo4j写入性能?

时间:2016-07-12 00:59:15

标签: neo4j neo4j-spatial

我一直在努力使用Neo4J 3.0.3为我的应用程序实现可接受的性能。以下是一些背景知识:

我正在尝试用Neo4j取代Apache Solr,以扩展其功能,同时保持或提高性能。

在Solr中,我的文档基本上是这样的:

{
"time": "2015-08-05T00:16:00Z",
"point": "45.8300018311,-129.759994507",
"sea_water_temperature": 18.49,
"sea_water_temperature_depth": 4,
"wind_speed": 6.48144,
"eastward_wind": 5.567876,
"northward_wind": -3.3178043,
"wind_depth": -15,
"sea_water_salinity": 32.19,
"sea_water_salinity_depth": 4,
"platform": 1,
"mission": 1,
"metadata": "KTDQ_20150805v20001_0016"
}

由于Solr是一个键值数据存储,我对Neo4J的初始翻译很简单,因此我可以感受到使用API​​。

我的方法基本上是让每个Solr记录等同于Neo4J节点,其中每个键值都将成为节点属性。

显然需要进行一些调整(将None改为' None'(python),将ISO时间更改为纪元时间(neo4j不支持索引日期时间),将点更改为lat / lon(neo4j空间索引)等等。)

我的目标是使用这个模型加载Neo4J,无论它有多天真。

以下是我在单个记录中加载时进行的休息调用的示例(使用http:localhost:7474 / db / data / cypher作为我的端点):

{
"query" : 
    "CREATE (r:record {lat : {lat}, SST : {SST}, meta : {meta}, lon : {lon}, time : {time}}) RETURN id(r);", 
"params": {
    "lat": 40.1021614075, 
    "SST": 6.521100044250488, 
    "meta": "KCEJ_20140418v20001_1430", 
    "lon": -70.8780212402, 
    "time": 1397883480
    }
}

请注意,我实际上删除了很多用于测试neo4j的参数。

目前我有严重的性能问题。将这样的文档加载到Solr中需要大约2秒钟。对于Neo4J,它需要:

使用REST API约20秒

使用BOLT约45秒

使用py2neo

<〜> 70秒

我需要加载~50,000,000条记录。在Solr中执行此操作通常需要24小时,因此Neo4J可能需要将近一个月的时间!

我记录了这些时间而没有在我的元素上使用唯一性约束。属性,而不将每个节点添加到空间索引中。这种情况导致的时间非常糟糕。

遇到这个问题,我尝试在线搜索性能调整。以下事情并没有改善我的情况:

- 将打开文件限制从1024增加到40000

- 使用ext4,并按照记录here

进行调整

- 将页面缓存大小增加到16 GB(我的系统有32个)

到目前为止,我只解决了加载时间问题。在我一夜之间加载了大约50,000个节点后,我尝试查询我的空间索引,如下所示:

CALL spatial.withinDistance('my_layer', lon : 34.0, lat : 20.0, 1000)

以及我的时间指数如此:

MATCH (r:record) WHERE r.time > {} AND r.time < {} RETURN r;

这些简单的查询几分钟就可以返回几个节点。

在Apache Solr中,空间索引非常快,并且在5秒内响应(即使加载了所有50000000个文档)。

此时,我担心这种性能滞后是否是由于我的数据模型的性质,服务器的配置等等。

我的目标是从这个模型中推断,并将几种测量类型移动到他们自己的Node类,并创建从我的基本记录节点到这些模型的关系。

我是否有可能滥用Neo4j,并且需要重新创建此模型以使用关系和几种不同的Node类型?我是否应该期待看到显着的改进?

作为旁注,我最初计划使用三重商店(特别是议会)来存储这些数据,并且在努力与RDF合作之后,决定Neo4J看起来很有前途并且更容易起床和运行。回到RDF是否值得一试?

欢迎任何建议,提示和评论。提前谢谢。

编辑:

正如评论中所建议的那样,我改变了加载脚本的行为。

以前我以这种方式使用python:

from neo4j.v1 import GraphDatabase
driver = GraphDatabase('http://localhost:7474/db/data')
session = driver.session()
for tuple in mydata:
    statement = build_statement(tuple)
    session.run(statement)
session.close()

使用这种方法,实际的.run()语句几乎没有时间运行。 .close()语句是所有运行时间发生的地方。

我的修改方法:

transaction = ''
for tuple in mydata:
    statement = build_statement(tuple)
    transaction += ('\n' + statement)
with session.begin_transaction() as tx:
    tx.run(transaction)
session.close()

我有点困惑,因为这种行为几乎是一样的。 .close()仍然需要大约45秒,除非它没有提交。因为我在每个语句中重用相同的标识符(CREATE(r:record {...}).... CREATE(r:record {...})...),我得到关于这个的CypherError行为。我现在还不知道如何避免这个问题,此外,运行时间似乎没有改善(我希望错误实际上使得终止更快)。

0 个答案:

没有答案