当我从Java中获得Cypher查询执行结果时,我遇到ResourceIterator<Node>
的结果检索速度非常慢。 next()
命令平均需要156毫秒,标准差为385! 这种行为是期待的,还是我做错了什么?任何人都可以提出一种更有效的方法来实现同样的目标吗?
我有以下图形布局,其中Point节点与其他点具有LinksTo关系:
节点:点
属性:
- idPoint (此属性上的新样式架构唯一约束)
- x (此属性上的新样式架构索引)
- y (此属性上的新样式架构索引)
关联:LinksTo
属性:
- idLink
- 长度
(...关系甚至在我的问题中都没有发挥作用......)
图表统计信息:
- 节点数:890,000
- 关系数:910,000
(在Ubuntu上使用Neo4j 2.0.0与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平均执行时间:&lt; 1 ms
command3平均执行时间:156毫秒(标准差为358)
(在每次迭代中找到500次迭代(不同坐标)和平均6个点的测量。测量是可重复的。)
(在Ubuntu上使用Neo4j 2.0.0与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 ms
command2平均执行时间:&lt; 1 ms
command3平均执行时间:112 ms(标准差为270)
(在每次迭代中找到500次迭代(不同坐标)和平均6个点的测量。测量是可重复的。)
答案 0 :(得分:1)
您所做的不是图表查询,而是对整个数据库进行范围扫描。
所以它必须拉入所有节点,并为每个节点进行比较。
您通常通过将节点放入树(r-tree)中来解决此问题,该树将几何图形编码为二维树结构,然后您可以仅log(levels)
复杂度访问所需的任何形状。 / p>
查看有关此主题的Neo4j空间的演示文稿:
http://neo4j.org/develop/spatial
您还强制Neo4j为每个节点重新解析并重新构建查询(500次)。
我同意Luanne的参数化,所以你的查询应该是这样的。
您也应该在for-loop
:
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,
map("xMin",xmMin,"xMax",xMax,"yMin",yMin,"yMax",yMax)); // query + params
...