技术开发 频道

NoSQL完胜MySQL:大规模图形遍历实战

  3、图形遍历

  对各数据库进行评估的遍历流程首先要从根顶点开始,此后的步骤都以此为起点,其中不加排序、也没有差异化处理。整个实验所需要的结果只有两个变量,即遍历长度与遍历过程开始的根顶点。在MySQL中,以下五条查询指令显示遍历长度为1到5.请注意,“?”是查询中的可变参数,代表遍历开始的根顶点。

SELECT a.inV FROM graph as a WHERE a.outV=?

SELECT b.inV FROM graph as a, graph as b WHERE a.inV=b.outV AND a.outV=?

SELECT c.inV FROM graph as a, graph as b, graph as c WHERE a.inV=b.outV AND b.inV=c.outV AND a.outV=?

SELECT d.inV FROM graph as a, graph as b, graph as c, graph as d WHERE a.inV=b.outV AND b.inV=c.outV AND c.inV=d.outV AND a.outV=?

SELECT e.inV FROM graph as a, graph as b, graph as c, graph as d, graph as e WHERE a.inV=b.outV AND b.inV=c.outV AND c.inV=d.outV AND d.inV=e.outV AND a.outV=?

  而在Neo4j方面使用的是Blueprint Pipe框架,即通过以下静态方法构建一个长度为n的通道。

public static Pipeline createPipeline(final Integer steps) {
  final ArrayList pipes
= new ArrayList();
  
for (int i = 0; i < steps; i++) {
    
Pipe pipe1 = new VertexEdgePipe(VertexEdgePipe.Step.OUT_EDGES);
    
Pipe pipe2 = new EdgeVertexPipe(EdgeVertexPipe.Step.IN_VERTEX);
    pipes.
add(pipe1);
    pipes.
add(pipe2);
  }
  
return new Pipeline(pipes);
}

  对于MySQL与Neo4j二者来说,查询结果(SQL与Pipe)都是循环访问。因此,全部结果都对应每条查询。在MySQL中,其作法如下。

while (resultSet.next()) {
  resultSet.getInt(finalColumn);
}

  Neo4j则采用以下方式。

while (pipeline.hasNext()) {
  pipeline.
next();
}

  4、实验结果

  用于测试的人工图形数据集是按照“多者愈多”的原则构建的优先连接模型。因此,创建时间越早的顶点,其密集程度就越大(即拥有最高的想邻顶点数量)。这一属性主要用于限制每次遍历过程所需要的测试评估时间。只有前250个顶点才会被作为遍历流程的起始顶点。在给出时间结果之前,请大家了解,全部实验都运行于一台搭载2.55GHz Intel Core 2 Duo处理器、4G 1067MHz DDR3内存的MacBook Pro笔记本上。所使用的软件为Java 1.6、MySQL JDBC 5.0.8以及Blueprints Pipes 0.1.2。

java version "1.6.0_17"
Java(TM) SE Runtime Environment (build
1.6.0_17-b04-248-10M3025)
Java HotSpot(TM)
64-Bit Server VM (build 14.3-b01-101, mixed mode)

  Java虚拟机采用如下所示的参数:

-Xmx1000M -Xms500M

  以下红色(代表MySQL)与蓝色(代表Neo4j)色块显示出遍历长度为1、2、3、4时的总体处理时间。

MySQL PK NoSQL:图形遍历和实验结果

  下列原始数据显示的是每次遍历过程所返回的总体顶点数量——当然,MySQL与Neo4j所返回的结果是相同的,也就是图形数据集中经过处理的部分。另外,考虑到遍历过程可以循环,因此有些顶点重复返回了多次。最后,请大家注意,只有Neo4j给出了长度为5的遍历过程的运行时间。MySQL用了两个小时也没搞定这项工作。相比之下,Neo4j在这一环节的耗时仅为14.37分钟。

[mysql steps-1] time(ms):124 -- vertices_returned:11360
[mysql steps-2] time(ms):922 -- vertices_returned:162640
[mysql steps-3] time(ms):8851 -- vertices_returned:2206437
[mysql steps-4] time(ms):112930 -- vertices_returned:28125623
[mysql steps-5] N/A

[neo4j steps-1] time(ms):27 -- vertices_returned:11360
[neo4j steps-2] time(ms):474 -- vertices_returned:162640
[neo4j steps-3] time(ms):3366 -- vertices_returned:2206437
[neo4j steps-4] time(ms):49312 -- vertices_returned:28125623
[neo4j steps-5] time(ms):862399 -- vertices_returned:358765631

  接下来,MySQL与Neo4j在个别数据点方面的处理能力如下图所示。每个点代表在不同遍历长度下,其往返于n个顶点所花费的时间。

MySQL PK NoSQL:图形遍历和实验结果

  最后,以下数据显示的是每次遍历过程每毫秒(平均)返回的顶点数量。同样,MySQL在2小时的时限内还是没能完成长度为5的遍历工作。

[mysql steps-1] time(ms):124 -- vertices_returned:11360
[mysql steps-2] time(ms):922 -- vertices_returned:162640
[mysql steps-3] time(ms):8851 -- vertices_returned:2206437
[mysql steps-4] time(ms):112930 -- vertices_returned:28125623
[mysql steps-5] N/A

[neo4j steps-1] time(ms):27 -- vertices_returned:11360
[neo4j steps-2] time(ms):474 -- vertices_returned:162640
[neo4j steps-3] time(ms):3366 -- vertices_returned:2206437
[neo4j steps-4] time(ms):49312 -- vertices_returned:28125623
[neo4j steps-5] time(ms):862399 -- vertices_returned:358765631

  总结

  鉴于本次遍历测试的对象是一款人工制作的自然统计数字图形,因此Neo4j本身的图形型数据库属性在优化方面当然要胜过关系型数据库MySQL。然而,在本次测试中没有对Java虚拟机以及SQL查询指令等项目进行优化。实验在Neo4j与MySQL中分别进行,在“即开即用”的前提下利用二者的“固有语法”处理这两类查询。

0