【问题标题】:Neo4j 2.0.0 - Poor performance for dev/test in a virtual machineNeo4j 2.0.0 - 虚拟机中的开发/测试性能不佳
【发布时间】:2014-01-15 18:45:12
【问题描述】:

我有 Neo4j 服务器在使用 Ubuntu 13.10 的虚拟机中运行,我正在使用 Cypher 查询通过 REST 访问。虚拟机有 4 GB 的内存分配给它。

我已将打开文件数更改为40000,将初始JVM堆设置为1G,我的neo4j.properties文件如下:

neostore.nodestore.db.mapped_memory=250M
neostore.relationshipstore.db.mapped_memory=100M
neostore.propertystore.db.mapped_memory=100M
neostore.propertystore.db.strings.mapped_memory=100M
neostore.propertystore.db.arrays.mapped_memory=100M

keep_logical_logs=3 days

node_auto_indexing=true
node_keys_indexable=id

我还根据 Neo4j Linux 调优指南更新了 sysctl:

vm.dirty_background_ratio = 50
vm.dirty_ratio = 80

由于我正在测试查询,基本例程是运行我的测试套件,然后删除所有节点并再次运行它们。在每次测试运行开始时,数据库中有 0 个节点。我的大约 100 个查询的测试套件需要 22 秒才能运行。基本参数化创建如:

CREATE (x:user { email: {param0},
  name: {param1},
  displayname: {param2},
  id: {param3},
  href: {param4},
  object: {param5} })
CREATE x-[:LOGIN]->(:login { password: {param6},
  salt: {param7} } )

目前执行时间超过 170 毫秒(这是平均值,第一次查询时间为 700 毫秒)。在测试运行期间,VM 中的 CPU 从未超过 50%,内存使用率稳定在 1.4Gb。

为什么在空数据库中创建单个节点需要 170 毫秒?在这一点上,单元测试变得几乎不可能,因为它太慢了。这是我第一次尝试调整 Neo4j,所以我不确定如何找出问题所在或应该进行哪些更改。

其他详情

我正在使用 Go 1.2 对本地安装的 Neo4j 实例的 cypher 端点 (http://localhost:7474/db/data/cypher) 进行 REST 调用。我将 content-type 的请求标头设置为“application/json”,接受“application/json”,将“X-Stream”设置为 true。根据查询,我总是返回一组地图或不返回任何内容。

似乎创造是问题,并且永远存在。例如:

2014/01/15 11:35:51 NewUser took 123.314938ms
2014/01/15 11:35:51 NewUser took 156.101784ms
2014/01/15 11:35:52 NewUser took 167.439442ms
2014/01/15 11:35:52 ValidatePassword took 4.287416ms

NewUser 创建两个新节点和一个关系,耗时 167 毫秒,而 ValidatePassword 是只读操作,完成时间为 4 毫秒。另请注意,对 NewUser 的三个调用是相同的参数化查询。虽然创建是个大问题,但我也有点担心当数据库中只有 100 个节点时,Neo4j 需要 4 毫秒才能找到一个标记的节点。

我不会在测试运行之间重新启动服务器或删除数据库。我在测试运行结束时发出一个删除所有节点查询MATCH (n) OPTIONAL MATCH (n)-[r]-() DELETE n,r。背靠背多次运行相同的测试套件并不会缩短查询时间。

【问题讨论】:

  • 在下面扩展了我的答案。

标签: performance neo4j cypher


【解决方案1】:

您的 100 个查询是否都相同,只是参数不同,还是实际上有 100 个不同的查询?

您看到的实际上是设置工作。解析器必须首先加载解析规则,这需要几毫秒。还没有看到的新查询被编译、计划并放入查询缓存中。

所以第一次查询总是需要更长的时间。但是当你参数化所有后续的应该很快。

你能确认一下吗?

我想你看到了将事务刷新到磁盘的transactional overhead。

您是否尝试将更多请求批处理为一个? IE。与事务端点?或者 /db/data/batch(但我宁愿使用新的 tx-endpoint /db/data/transaction)。

您是否为验证查询的查找属性创建了索引?

您能帮我一个忙并在没有标签的情况下测试您的创建查询吗?我在本周早些时候自己测试时发现了一些性能问题。

刚刚用 curl 进行了测试

for i in `seq 1 10`; do time curl -i -H content-type:application/json -H accept:application/json -H X-Stream:true -d @perf_test.json http://localhost:7474/db/data/cypher; done

每个外部请求的时间在 16 到 30 毫秒之间,包括启动 curl

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8; stream=true
Access-Control-Allow-Origin: *
Transfer-Encoding: chunked
Server: Jetty(9.0.5.v20130815)

{"columns":[],"data":[]}
real    0m0.016s
user    0m0.005s
sys 0m0.005s

也许是虚拟机(磁盘或网络)或跨虚拟机通信?

对两个端点使用 ab 和 1000 个请求进行了另一次测试,两次的平均时间约为 5 毫秒。

https://gist.github.com/jexp/8452037

【讨论】:

  • 测试套件中的查询大多是唯一的,但我一遍又一遍地运行相同的测试套件,它应该缓存执行计划(我希望?)。在启动 Neo4j 后测试套件的第一次运行中,基本创建可能需要 700 毫秒,后续运行需要 170 毫秒。似乎第一次运行 700 毫秒仍然很长,但如果后续运行速度很快,我可以忍受。
  • 您是否在这期间重新启动服务器?你使用什么样的驱动程序?还是您自己调用 REST 端点?如果这是 2.0,我建议使用事务端点。也许您可以分享有关如何执行查询的更多详细信息?
  • 我在上面的问题中添加了更多细节。
  • 如果我删除标签没有变化。我不是在尝试进行大型数据导入,我实际上是在尝试插入 2 个节点和 1 个关系,这一切都在单个 Cypher 查询中完成。没有要批处理的东西。有没有办法告诉 Neo4j 不要刷新到磁盘?此外,我还为验证查询上的查找属性创建了一个索引。
  • 没有批处理,我的意思是每个测试都是独立的。每个测试同步运行一个 Cypher 查询,然后在继续下一个测试之前验证结果。这是针对 Web 服务的,因此它在生产环境中也是如此 - 我等不及要收到一堆请求并尝试在响应之前对它们进行批处理。
猜你喜欢
  • 2016-12-28
  • 2010-10-13
  • 2010-11-29
  • 1970-01-01
  • 1970-01-01
  • 2014-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多