【问题标题】:Comparsion between friend-of-friend-of-friend-of... relationships in MySQL and Neo4JMySQL和Neo4J中friend-of-friend-of-friend-of...关系的比较
【发布时间】:2012-12-11 12:19:57
【问题描述】:

为了了解使用 Neo4J 建立朋友关系的优势,我在 MySQL 数据库上为 Persons 创建了一个表(“Persons”,20900 个数据集):

id     | name
--------------
 1     | Peter
 2     | Max
 3     | Sam
 ...   | ...
 20900 | Rudi

和一张关系表(“友谊”,每个人有 50 到 100 个朋友):

personen_id_1 | personen_id_2
-------------------------
 1         | 2
 1         | 3
 2         | 56
 ...       | ...
 20900     | 201

所以,大约有 120 万个关系。

现在我想现在是 id=1 的 Person 的friends-of-friends-of-friends-of-friends,所以我制作了这样的查询:

select distinct P.name
from Friendships f
join Friendships f2 ON f.personen_id_2 = f2.personen_id_1
join Friendships f3 ON f2.personen_id_2 = f3.personen_id_1
join Friendships f4 ON f3.personen_id_2 = f4.personen_id_1
join Persons P ON f4.personen_id_2 = P.id
where f.personen_id_1 = 1

user-id 1 的查询花费了大约 30 秒

在 Neo4J 中,我为每个人创建了一个具有一个名称属性的节点(20900 个节点)。所有节点都与 MySQL 中的 Friendships-table 连接,因此有 120 万个关系。

为了在此处获得相同的 finedset,我输入了 gremlin:

gremlin> g.v(1).outE.inV.loop(2){ it.loops <= 4 }.name.dedup.map()

这花了大约 1 分钟。我根本没想到会这样!

所以我的比较正确吗?如果是,如何修改此示例以显示使用 neo4j 完成此任务的优势?

【问题讨论】:

  • 您使用了什么 JVM 设置?你的硬件是什么? JVM 的默认内存设置对于数据库来说太小了。如果这是第一次运行,它只会测量您的磁盘速度以提取数据。
  • 我使用 oracle jvm 1.6,堆大小设置为java -Xms 1G -Xmx 1G

标签: mysql graph neo4j gremlin


【解决方案1】:

如果您知道自己正在执行 4 个循环,请执行以下操作:

g.v(1).out.out.out.out.name.dedup.map

Gremlin 中存在一个已知的语义错误,其中 loop() 将变成广度优先查询。 https://github.com/tinkerpop/pipes/issues/25

此外,如果不需要,请不要执行 outE.inV。等价的已经出来了。此外,请意识到您正在执行 4 步搜索,即大规模计算(组合爆炸)。这是图数据库不擅长的事情。为此,您将需要查看像 Faunus 这样的批处理分析框架 -- http://thinkaurelius.github.com/faunus/。原因见http://thinkaurelius.com/2012/04/21/loopy-lattices/

图形数据库针对本地遍历进行了优化,通过 4 个步骤,您(很可能)触及了整个数据集并使用“get get get”样式的数据库访问,这效率不高。

HTH, 马尔科。

【讨论】:

  • 好的,但我认为这应该比 mysql 中的相同 szenario 更有效?!
【解决方案2】:

我对 Gremlin 并不太熟悉,但我生成了一个类似大小的数据集(以下统计数据)并在 Cypher 中运行了一个等效查询:

START person=node:user(name={name})
MATCH person-[:FRIEND]-()-[:FRIEND]-()-[:FRIEND]-()-[:FRIEND]-friend
RETURN friend.name AS name

我对数据集运行了 1000 次,每次都选择不同的用户作为起点。在运行测试之前我没有预热缓存,所以这是从一开始就开始的。平均响应时间:33 毫秒。

在 MacBook Pro、2.2 GHz Intel Core i7、8 GB RAM、4 GB 堆上运行

以下是图表统计数据:

+----------------------------------------------+
| user           | 20900                       |
+----------------------------------------------+
|                | Average |    High |     Low |
+----------------------------------------------+
| FRIEND                                       |
+----------------------------------------------+
|       OUTGOING |      74 |     100 |      48 |
|       incoming |      74 |     123 |      31 |
+----------------------------------------------+

+----------------------------------------------+
| _UNKNOWN       | 1                           |
+----------------------------------------------+
|                | Average |    High |     Low |
+----------------------------------------------+

+----------------------------------------------+
| Totals                                       |
+----------------------------------------------+
| Nodes          | 20901                       |
| Relationships  | 1565787                     |
+----------------------------------------------+
| FRIEND         | 1565787                     |
+----------------------------------------------+

【讨论】:

  • 我的规格:Corei5 2.5GHz,8GB 内存,2GB Java 堆大小。在增加节点和关系的 memeory-io 映射的 RAM 大小之后,例如neostore.nodestore.db.mapped_memory=1000M neostore.relationshipstore.db.mapped_memory=1000M 查询耗时 30 秒,还是太长了
  • 密码查询和 gremlin 中的一样慢
  • 使用您的数据集,在深度 4,每个人都可能与其他人连接。如果每个人正好有 100 个朋友,那么深度 4 搜索将遍历 100 x 100 x 100 x 100 个关系,即 100,000,000 次遍历,或访问的 100,000,000 个实体。在商品硬件上,Neo4j 通常每秒可以遍历 1-200 万个关系,即每秒 1-200 万个连接。所以数字加起来。如果这是一个真实的域,我们可能只需要深度 4 的前 100 或 1000 人:如果您将结果迭代 100 次,您将获得低毫秒响应。
  • 你能举个例子,在 gremlin 中只获取深度 4 搜索的前 100 个节点吗?
  • 在 Cypher 中,这看起来像 START person=node:user(name={name}) MATCH person-[:FRIEND]-()-[:FRIEND]-()-[:FRIEND]-()-[:FRIEND]-friend RETURN friend.name AS name LIMIT 100,请务必为此使用 Neo4j 1.9.M02,因为对此进行了一些重大优化。
猜你喜欢
  • 1970-01-01
  • 2012-05-20
  • 2013-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-11
  • 2012-09-30
  • 1970-01-01
相关资源
最近更新 更多