本文作者Marko A.Rodriguez博士是一位图形系统顾问,其研究重点主要是图形/网络领域的理论及实践类问题。这篇文章以一次简单的图形遍历任务为基础,为大家并行展示MySQL与Neo4j在这方面的处理能力。
MySQL PK NoSQL:大规模图形遍历能力

本文所使用的数据集为一幅人工生成的统计图,该图形由一百万个顶点与四百万条边线构成。其角度分布汇总结果如以下对数坐标图所示。图形的全部顶点分为一千个顶点子集,具体排布情况见上图。
 

MySQL PK NoSQL:大规模图形遍历能力

1、载入图形

  图形数据集被分别加载到MySQL与Neo4j当中。在MySQL方面,使用如下模式的单独列表加以处理。

CREATE TABLE graph (
  outV INT NOT NULL,
  inV INT NOT NULL
);
CREATE INDEX outV_index USING BTREE ON graph (outV);
CREATE INDEX inV_index USING BTREE ON graph (inV);
  数据载入完成后,列表内容如下所示。第一行的内容意为:“顶点0与顶点1相连。”

mysql> SELECT * FROM graph LIMIT 10;
+------+-----+
| outV | inV |
+------+-----+
|    0 |   1 |
|    0 |   2 |
|    0 |   6 |
|    0 |   7 |
|    0 |   8 |
|    0 |   9 |
|    0 |  10 |
|    0 |  12 |
|    0 |  19 |
|    0 |  25 |
+------+-----+
10 rows in set (0.04 sec)
  这一拥有一百万个顶点的数据集同样被载入Neo4j之中。在Gremlin中,图形边界按以下方式描述。第一行内容意为:“顶点0与顶点992915相连。”

gremlin> g.E[1..10]
==>e[183][0-related->992915]
==>e[182][0-related->952836]
==>e[181][0-related->910150]
==>e[180][0-related->897901]
==>e[179][0-related->871349]
==>e[178][0-related->857804]
==>e[177][0-related->798969]
==>e[176][0-related->773168]
==>e[175][0-related->725516]
==>e[174][0-related->700292]
  2、为缓存热身

  在利用MySQL与Neo4j对图形数据结构进行遍历之前,两款数据库都应该进行一下“热身”运动。在MySQL方面,先运行“SELECT * FROM graph(选择所有图形内容)”指令,而且全部结果都经过了循环访问。而在Neo4j中,则对图形中的每个顶点进行循环访问并对每个顶点的延展边界加以检索。最后,将整个实验流程在MySQL与Neo4j中各运行两遍,并根据第二次得出的结果进行评估。
  以下红色(代表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中分别进行,在“即开即用”的前提下利用二者的“固有语法”处理这两类查询。