【发布时间】:2014-01-15 13:29:13
【问题描述】:
当我从 Java 中的 Cypher 查询执行中获取结果时,我使用 ResourceIterator<Node> 检索结果的速度出奇地慢。 next() 命令平均耗时 156 毫秒,标准差为 385! 这是预期的行为,还是我做错了什么?任何人都可以提出一种更有效的方法来实现同样的目标吗?
图形结构
我有以下图形布局,其中 Point 节点与其他点有 LinksTo 关系:
节点:点
属性:
- idPoint(此属性的新样式模式唯一约束)
- x(此属性的新样式模式索引)
- y(此属性的新样式模式索引)
Relation:LinksTo
属性:
- idLink
- 长度
(......关系甚至在我的问题中都没有发挥作用......)
图表统计:
- 节点数:890,000
- 关系数:910,000
旧代码
(在 Ubuntu 上使用 Neo4j 2.0.0 stable 和 Oracle Java 7)
(基本上,此代码在给定点周围的 60x60 正方形中搜索节点(点)。)
GraphDatabaseService graphDB = new GraphDatabaseFactory ( ).newEmbeddedDatabase ("points_db");
ExecutionEngine engine = new ExecutionEngine (graphDB);
for (Coordinate c : coords) // coords holds 500 different coordinates
{
int size = 30;
int xMin = c.x - size;
int xMax = c.x + size;
int yMin = c.y - size;
int yMax = c.y + size;
String query = "MATCH (n:POINT) " +
" WHERE n.x > " + xMin +
" AND n.x < " + xMax +
" AND n.y > " + yMin +
" AND n.y < " + yMax +
"RETURN n AS neighbour";
ExecutionResult result = engine.execute (query); // command1
ResourceIterator<Node> ri = result.columnAs ("neighbour"); // command2
while (ri.hasNext ( ))
{
Node n = ri.next ( ); // command3
// ... some code ...
}
}
测量
command1 平均执行时间:7.5 毫秒
command2 平均执行时间:
command3 平均执行时间:156 毫秒(标准差为 358)
(使用 500 次迭代(不同坐标)进行的测量,每次迭代平均找到 6 个点。测量是可重复的。)
编辑 1(根据 Luanne 和 Michael 的建议)
新的、更快的参数化代码
(在 Ubuntu 上使用 Neo4j 2.0.0 stable 和 Oracle Java 7)
(基本上,此代码在给定点周围的 60x60 正方形中搜索节点(点)。)
GraphDatabaseService graphDB = new GraphDatabaseFactory ( ).newEmbeddedDatabase ("points_db");
ExecutionEngine engine = new ExecutionEngine (graphDB);
Map<String, Object> params = new HashMap<> ( );
int size = 30;
String query = "MATCH (n:POINT) " +
" WHERE n.x > {xMin}" +
" AND n.x < {xMax}" +
" AND n.y > {yMin}" +
" AND n.y < {yMax}" +
" RETURN n AS neighbour";
for (Coordinate c : coords) // coords holds 500 different coordinates
{
params.put ("xMin", (int) c.x - size);
params.put ("xMax", (int) c.x + size);
params.put ("yMin", (int) c.y - size);
params.put ("yMax", (int) c.y + size);
ExecutionResult result = engine.execute (query, params); // command1
ResourceIterator<Node> ri = result.columnAs ("neighbour"); // command2
while (ri.hasNext ( ))
{
Node n = ri.next ( ); // command3
// ... some code ...
}
}
测量
command1 平均执行时间:1.7 毫秒
command2 平均执行时间:
command3 平均执行时间:112 毫秒(标准差为 270)
(使用 500 次迭代(不同坐标)进行的测量,每次迭代平均找到 6 个点。测量是可重复的。)
【问题讨论】:
-
您可以先参数化您的查询然后测量时间吗? docs.neo4j.org/chunked/milestone/cypher-parameters.html
-
这里有一个错字:
negihbour。 -
参数化的好建议。我改进了代码,新的测量明显更快。但我会说他们仍然在“同一个球场”。