使用MySQL和Neo4j是一个好主意吗?
我会用很多相似的项目(百万)来创建一个应用程序,并且我想将它们存储在一个MySQL数据库中,因为我想进行大量统计并搜索特定列的特定值。使用MySQL和Neo4j是一个好主意吗?
但是与此同时,我将存储所有项目之间的关系,这些项目在许多连接的二叉树状结构(传递闭包)中是相关的,而关系数据库并不擅长这种结构,所以我希望将所有关系存储在Neo4j中,这些数据具有良好的性能。
我的计划是除了MySQL数据库中的关系之外的所有数据以及存储在Neo4j数据库中的与item_id
的所有关系。当我想查找一棵树,我先搜索的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查询将如何执行?
在此谈几点想法:
我会尝试造型的Neo4j的域模型,包括图中每个节点的属性。通过将数据分成两个不同的数据存储区,您可能会限制您可能想要执行的一些操作。
我想这归结于您将使用图表做什么?例如,如果想要查找连接到特定节点的所有节点,其属性(即名称,年龄等)是否为特定值,您首先必须在MySQL数据库中找到正确的节点ID,然后再进入Neo4j。当你可以在Neo4j中完成所有这些时,这看起来很慢并且过于复杂。所以问题在于当遍历图时你需要节点的属性吗?
您的数据会改变还是静态?通过拥有两个独立的数据存储区,会使问题复杂化。
虽然使用MySQL数据库生成统计数据可能比Neo4j的,遍历图来查找符合规定条件的所有节点所需的代码所做的一切更容易是不是太困难。这些统计数据应该推动你的解决方案。
我不能在MySQL查询的性能评价来选择节点ID。我想这涉及到您需要选择多少个节点以及您的索引策略。当我谈到遍历图时,我同意关于事物的性能方面。
这是一篇很好的文章:MySQL vs. Neo4j on a Large-Scale Graph Traversal在这种情况下,当他们说大的时候,它们只意味着一百万个顶点/节点和四百万个边。所以它甚至不是一个特别密集的图。
危险包括更多的属性是你最终会在图形数据库中锁定所有的数据。我认为能够轻松组合多种类型的数据存储并且也容易报告这种情况是必要的。 – Eelco 2011-06-09 19:44:59
为什么“这看起来很慢”?如果我从neo4j查询中检索id,然后在关系上创建'WHERE IN(ids)',为什么它应该很慢?通过大量的表进行连接会快得多,不是吗?谢谢! – Luccas 2013-04-05 20:13:59
@Luccas,“这看起来很慢并且过于复杂”,因为对于大多数这些查询,您可以直接在neo4j中执行它们,并且不需要在不同的dbs中执行2个查询,尽管(primary)索引id上的sql查询将会显然会很快。 – vish4071 2017-07-31 06:22:41
您可以通过使用改进查询:
SELECT *
FROM items
WHERE item_id IN (45, 345435, 343, 78, 4522, 676, 443, 4255, 4345)
这也是不完全正确的是关系型数据库是存储在树形结构不好。当然,MySQL缺少一些使它更容易的功能,但大多数其他数据库都支持它。 Oracle有CONNECT BY
。大多数主流RDBMS都有某种形式的递归查询--MySQL是一个明显的例外。也许你可以看看PostgreSQL,看看它是否符合你的需求?
或者使用嵌套集合,这对于在路径/子树上执行读取操作很有帮助。然而,无论采取什么方法,它仍然感觉非常像对抗我的工具,而使用图形数据库处理适当的数据感觉很自然,并且具有特定优化和可视化等附加益处(至少是理论上的)。 – Eelco 2011-06-09 19:48:43
我主要是在这方面与Binary Nerd,但是想添加一个变体。您可以将实时数据存储在Neo4j中,然后提取需要的数据用于统计/报告并存入MySQL。对于搜索,如果符合您的需求,我会使用Neo4j-Lucene integration。
关系数据库可以处理图形结构。他们中的一些甚至可以轻松地处理它们(就像关系数据库那样优雅!)。
关系数据库中一般图处理的关键是recursive common table expression(RCTE),它基本上允许您通过组合一个查询来选择一个根,从而基本上允许您迭代(不管是否为名称)递归查询一组行和一个查询,该查询定义到目前为止选择的行的邻居。语法有点笨重,但它通用而且功能强大。
RCTE在PostgreSQL,Firebird,SQL Server和DB2显然都支持。 Oracle具有不同但等同的构造;我读过最近的版本支持正确的RCTE。 MySQL不支持RCTE。如果你不熟悉MySQL,我会敦促你考虑使用PostgreSQL,它基本上是一个更好的数据库。
但是,这听起来像你不需要支持一般图形,只是树木。在这种情况下,您可以选择更多具体的选项。
其中一个是经典,但非常灵活nested sets。
一个更简单的方法是存储每行的路径:这是一个字符串,表示树在树中的位置,并且具有属性,即节点的路径是任何子节点的路径的前缀,让您可以非常有效地进行关于祖先的各种查询(“节点A是节点B的孩子?”,“节点A和节点B的最低共同祖先是什么?”等)。例如,您可以通过从根目录树走过来,为路径构建一条路径,并将路径中遇到的行的ID与斜线连接起来。这很容易构建,但是如果重新排列树,确实需要注意。使用路径列,只需添加and path like '23/%'
即可将查询限制为给定树,其中23
是根的ID。
因此,虽然图形数据库可能是存储和查询图形数据的最佳方式,但它不是唯一的选择,我建议你衡量使用一个优点来对抗所有数据的优点单一数据库。
可以用“IN”子句替换不同的“OR”:) – Mik378 2013-11-13 12:55:18
@Jonas你最终做了什么。我很想知道你是如何解决问题的? – Medorator 2014-05-15 12:41:47
对于这个问题的新读者:在[Java持续企业发展](http://shop.oreilly.com/product/0636920025368.do)和[this code](https://github.com/arquillian /持续企业开发)使用这种架构溶剂。有一个章节证明混合两个数据库的选择是合理的。 – Mats 2015-09-15 21:31:22