使用MySQL和Neo4j一起是否是一个好主意?

54

我将创建一个包含大量相似项(数百万个)的应用程序,并希望将它们存储在MySQL数据库中,因为我想对特定列的特定值进行统计和搜索。

但同时,我将存储所有项目之间的关系,这些关系以许多连接的二叉树结构(传递闭包)相关联,关系数据库不擅长处理这种结构,因此我想将所有关系存储在Neo4j中,因为它对这种数据有很好的性能。

我的计划是除了关系之外的所有数据都存储在MySQL数据库中,而所有关系及其item_id 存储在Neo4j数据库中。当我想要查找树时,我首先在Neo4j中搜索树中的所有item_id,然后在MySQL数据库中搜索所有指定项目的查询,类似于:

SELECT * FROM items WHERE item_id = 45 OR item_id = 345435 OR item_id = 343 OR item_id = 78 OR item_id = 4522 OR item_id = 676 OR item_id = 443 OR item_id = 4255 OR item_id = 4345

这是个好主意还是错了? 我以前没有使用过图形数据库。有更好的方法来解决我的问题吗?在这种情况下,MySQL查询的性能如何?


9
可以使用“IN”子句替换不同的“OR” :) - Mik378
1
@Jonas,你最终做了什么?我很想知道你是如何解决这个问题的? - user
1
对于这个问题的新读者:在书籍Java连续企业开发此代码中使用了这种架构解决方案。有一个章节来证明将两个数据库混合在一起的选择是正确的。 - Mats
4个回答

31
一些想法:
我建议您尝试对Neo4j领域模型进行建模,以包括图中每个节点的属性。将数据分为两个不同的数据存储可能会限制一些您想要执行的操作。
关键在于您将使用图形进行什么操作。例如,如果您想找到与某些属性(例如名称、年龄等)具有特定值的特定节点相连的所有节点,是否需要先在MySQL数据库中找到正确的节点ID,然后进入Neo4j?这似乎很慢且过于复杂,因为您可以在Neo4j中完成所有这些操作。因此,问题是:在遍历图形时,您是否需要节点的属性?
您的数据是否会更改或是静态的?通过拥有两个单独的数据存储库,这将使事情变得更加复杂。
虽然使用MySQL数据库生成统计信息可能比在Neo4j中执行所有操作更容易,但用于遍历图形以查找符合定义标准的所有节点所需的代码并不过于困难。这些统计信息应该驱动您的解决方案。
我无法评论选择节点ID的MySQL查询的性能。这取决于您需要选择多少节点以及您的索引策略。不过,当涉及遍历图形时,我同意性能方面的考虑。
这是一个关于此的好文章:MySQL vs. Neo4j on a Large-Scale Graph Traversal,在这种情况下,当他们说大时,他们只指一百万个顶点/节点和四百万条边。因此,这甚至不是一个特别密集的图形。

包含更多属性的危险在于你最终会把所有数据都塞进图形数据库中。我认为轻松地组合多种类型的数据存储并轻松地对其进行报告是必要的。 - Eelco
1
为什么会出现“这个看起来很慢”的情况?如果我从Neo4j查询中检索id,然后在关系型数据库上进行WHERE IN(ids)操作,为什么它应该很慢呢?相比于遍历许多表并进行连接,这种方法不是更快吗?谢谢! - Luccas
1
@Luccas,“这似乎很慢且过于复杂”,因为对于大多数这些查询,您可以直接在neo4j中执行它们,而不需要在不同的数据库中执行2个查询,尽管在(主要)索引ID上执行SQL查询显然会很快。 - vish4071

12

关系型数据库可以处理图形结构,其中一些甚至可以相当优雅地处理它们(就像一个关系型数据库能做到的那样优雅!)。

在关系型数据库中处理通用图形的关键是 递归公共表达式(RCTE),它基本上让您通过组合选择根行集和定义到目前为止选择的行的邻居的查询来迭代(而不是递归,尽管名称中包含递归)扩展一组行的查询。 语法有点笨拙,但它是通用且功能强大的。

RCTE 受 PostgreSQL、Firebird、SQL Server 和显然是 DB2 的支持。Oracle 有一个不同但等效的结构;我已经阅读过最新版本支持适当的 RCTE。MySQL 不支持 RCTE。如果你没有依赖于 MySQL,我建议你考虑使用 PostgreSQL,它基本上是一个全方位更好的数据库。

然而,看起来你不需要支持通用图形,只需要支持树形结构。在这种情况下,你可以选择更具体的选项。

其中之一是经典但相当令人费解的嵌套集合

另一种更简单的方法是在每行中存储路径:这是表示该行在树中位置的字符串,并具有节点路径是任何子节点的前缀的属性,这使您可以非常有效地执行各种关于祖先的查询(“节点 A 是节点 B 的子节点吗?”,“节点 A 和节点 B 的最低公共祖先是什么?”等)。例如,您可以通过从根遍历树并使用斜杠连接所遇到的行的 ID 来构造行的路径。这很容易构建,但如果重新排列树,则需要小心维护它。使用路径列,您可以通过添加 and path like '23/%' 限制查询到给定的树,其中 23 是根的 ID。

因此,虽然图形数据库可能是存储和查询图形数据的最佳选择,但它并不是唯一的选择。我建议您权衡使用图形数据库的优势和将所有数据存储在单个数据库中的优势。


6

我基本上同意Binary Nerd的观点,但是想要添加一些变化。您可以将实时数据存储在Neo4j中,然后提取需要用于统计/报告的数据并放入MySQL中。对于搜索,如果符合您的需求,我会选择Neo4j-Lucene集成


4

您可以使用IN来改进查询:

SELECT *
FROM items
WHERE item_id IN (45, 345435, 343, 78, 4522, 676, 443, 4255, 4345)

并不是说关系型数据库完全不适合存储树形结构。虽然MySQL缺少一些功能,使得存储树形结构变得困难,但大多数其他数据库都支持得很好。Oracle有CONNECT BY。大多数主流的关系型数据库管理系统都具有某种形式的递归查询,MySQL则是一个明显的例外。也许你可以看看PostgreSQL,看它是否符合你的需求?


3
或者使用嵌套集,这对于在路径/子树上执行读取操作非常有效。然而,无论采用哪种方法,它仍然让我感觉像是在与工具作斗争,而使用图形数据库处理适当的数据则感觉很自然,并且具有特定的优化和可视化等附加好处(至少在理论上是这样)。 - Eelco

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接