【问题标题】:Is it a good idea to use MySQL and Neo4j together?一起使用 MySQL 和 Neo4j 是个好主意吗?
【发布时间】:2010-03-29 23:16:06
【问题描述】:

我将制作一个包含很多类似项目(数百万)的应用程序,我想将它们存储在 MySQL 数据库中,因为我想做很多统计数据并搜索特定列的特定值。

但同时,我将存储所有项目之间的关系,它们在许多连接的二叉树状结构(传递闭包)中相关,而关系数据库不擅长这种结构,所以我会喜欢在 Neo4j 中存储对此类数据有良好性能的所有关系。

我的计划是将除了 MySQL 数据库中的关系以及与item_id 的所有关系之外的所有数据都存储在 Neo4j 数据库中。当我想查找树时,我首先在 Neo4j 中搜索树中的所有 item_id:s,然后在 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 查询将如何执行?

【问题讨论】:

  • 可以用“IN”子句替换不同的“OR” :)
  • @Jonas 你最后做了什么。我很想知道您是如何解决问题的?
  • 对于这个问题的新读者:在书中Continuous Enterprise Development in Javathis code 使用了这个架构解决方案。有一章证明选择混合两个数据库是合理的。

标签: architecture mysql hierarchical-data neo4j graph-databases


【解决方案1】:

对此的想法很少:

我会尝试对您的 Neo4j 域模型进行建模,以在图中包含每个节点的属性。通过将您的数据分成两个不同的数据存储,您可能会限制您可能想要执行的一些操作。

我想这取决于您将如何处理图表。例如,如果您想查找连接到特定节点的所有节点,其属性(即名称、年龄……等等)是特定值,您是否首先必须在 MySQL 数据库中找到正确的节点 ID,然后进入新4j?当您可以在 Neo4j 中完成所有这些操作时,这似乎很慢而且过于复杂。那么问题来了:遍历图的时候需要节点的属性吗?

您的数据会改变还是静态的?拥有两个独立的数据存储会使事情复杂化。

虽然使用 MySQL 数据库生成统计数据可能比在 Neo4j 中执行所有操作更容易,但遍历图以查找满足定义条件的所有节点所需的代码并不太难。这些统计数据应该推动您的解决方案。

我无法评论 MySQL 查询选择节点 ID 的性能。我想这取决于您需要选择多少个节点以及您的索引策略。不过,我同意遍历图表时的性能方面。

这是一篇很好的文章:MySQL vs. Neo4j on a Large-Scale Graph Traversal,在这种情况下,当他们说大时,他们只表示一百万个顶点/节点和四百万条边。所以它甚至不是一个特别密集的图。

【讨论】:

  • 包含更多属性的危险在于您最终会将所有数据硬塞到图形数据库中。我认为能够轻松组合多种类型的数据存储并轻松进行报告是必要的。
  • 为什么“这看起来很慢”?如果我从 neo4j 查询中检索 id,然后在关系上创建 WHERE IN (ids),为什么它应该很慢?比遍历很多表进行连接要快得多,不是吗?谢谢!
  • @Luccas,“这似乎很慢而且过于复杂”,因为对于这些查询中的大多数,您可以直接在 neo4j 中执行它们,并且不需要在不同的 dbs 中执行 2 个查询,尽管 sql 查询on (primary) index id 显然会很快。
【解决方案2】:

关系数据库可以处理图形结构。其中一些甚至可以适度优雅地处理它们(就像关系数据库一样优雅!)。

关系数据库中通用图形处理的关键是recursive common table expression (RCTE),它基本上允许您通过组合一个选择一个行的根集和定义到目前为止所选行的邻居的查询。语法有点笨拙,但是通用且强大。

在 PostgreSQL、Firebird、SQL Server 和 DB2 中显然支持 RCTE。 Oracle 有一个不同但等效的结构。我读过最近的版本支持正确的 RCTE。 MySQL 不支持 RCTE。如果你不喜欢 MySQL,我建议你考虑使用 PostgreSQL,它基本上是一个全面的数据库。

但是,听起来您不需要支持一般图表,只需要支持树。在这种情况下,您可以选择更具体的选项。

一个是经典但相当令人费解的nested sets

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

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

【讨论】:

    【解决方案3】:

    我主要支持 Binary Nerd,但想添加一个变体。您可以将实时数据存储在 Neo4j 中,然后提取统计/报告所需的数据并放入 MySQL。对于搜索,如果符合您的需要,我会使用 Neo4j-Lucene integration

    【讨论】:

      【解决方案4】:

      您可以使用 IN 改进查询:

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

      关系型数据库不擅长存储树形结构也不完全正确。当然 MySQL 缺少一些使它更容易的功能,但大多数其他数据库都很好地支持它。甲骨文有CONNECT BY。大多数主流 RDBMS 都有某种形式的递归查询 - MySQL 是一个明显的例外。或许您可以看看 PostgreSQL,看看它是否满足您的需求?

      【讨论】:

      • 或者使用嵌套集,这对于在路径/子树上进行读取操作很有用。但是,无论您采用哪种方法,对我来说,它仍然很像与该工具作斗争,而使用图形数据库获取适当的数据感觉很自然,并且具有特定优化和可视化等额外的好处(至少理论上)。
      猜你喜欢
      • 1970-01-01
      • 2014-02-10
      • 1970-01-01
      • 2013-06-17
      • 1970-01-01
      • 2014-10-09
      • 1970-01-01
      • 2013-03-09
      • 1970-01-01
      相关资源
      最近更新 更多