从关系型数据库过渡到图数据库

本页面探讨了关系型数据库和图数据库在结构和数据模型上的概念差异。它还从高层次概述了两种数据库类型的工作方式异同——从关系型和图查询语言到应用程序与数据库的交互方式。

关系型数据库概述

关系型数据库将高度结构化的数据存储在表中,这些表具有预定的特定类型列和定义类型的信息行。由于其组织的严格性,关系型数据库要求开发人员和应用程序严格地组织其应用程序中使用的数据。

在关系型数据库中,对其他行和表的引用通过外键列引用主键属性来表示。连接在查询时通过匹配所有相关表中的主键和外键来计算。这些操作计算量大、内存密集,并且具有指数级的成本。

当模型中出现多对多关系时,您必须引入一个连接表(或关联实体表),该表包含两个参与表的外键,从而进一步增加连接操作成本,如图所示

该图展示了通过创建人员-部门连接表(其中一列包含人员 ID,下一列包含关联部门 ID),将人员(来自人员表)连接到部门(在部门表中)的概念。

这种结构使得理解连接变得麻烦,因为您必须知道人员 ID 和部门 ID 值(执行额外查找以找到它们),才能知道哪个人连接到哪个部门。这些高成本的连接操作通常通过数据非规范化来解决,以减少所需的连接数量,从而破坏关系型数据库的数据完整性。

图数据库适用于不适合关系型数据模型的用例,并为连接数据提供了新的可能性。

将关系型知识转换为图

与其他数据库管理系统不同,在图数据模型中,关系与数据本身同等重要。这意味着我们无需使用外键等特殊属性或 MapReduce 等带外处理来推断实体之间的连接。

通过将节点和关系组装成连接结构,图数据库使我们能够构建与问题域紧密映射的简单而复杂的模型。数据与现实世界中的形式惊人地相似——小型、规范化但连接丰富的实体。这使您可以从任何可想象的兴趣点查询和查看数据,支持多种不同的用例。

图数据库模型中的每个节点(实体或属性)直接且物理地包含一个关系记录列表,这些记录表示与其他节点的关系。这些关系记录按类型和方向组织,并可能包含附加属性。每当您运行相当于连接操作时,图数据库都会使用此列表,直接访问连接的节点,从而无需进行昂贵的搜索和匹配计算。

这种将关系预物化到数据库结构中的能力使 Neo4j 能够提供比其他数据库高出几个数量级的性能,特别是对于连接繁重的查询,从而让用户获得分钟到毫秒的优势。

数据模型差异

正如您可能从上面讨论的结构差异中想象的那样,关系型数据模型与图数据模型非常不同。直观的图结构产生的数据模型比使用传统关系型或其他 NoSQL 数据库产生的数据模型更简单、更具表现力。

如果您习惯于使用关系型数据库进行建模,请记住设计良好、规范化的实体关系图的简单性和美观性——一个您可以快速与同事和领域专家在白板上讨论的简单易懂的模型。图正是如此——一个清晰的领域模型,专注于您想要高效支持的用例。

让我们比较这两种数据模型,以展示关系型和图之间的结构差异。

在上面的关系型示例中,我们搜索左侧的“人员”表(可能包含数百万行)以找到用户 Alice 和她的个人 ID 815。然后,我们搜索“人员-部门”表(橙色中间表)以找到所有引用 Alice 个人 ID (815) 的行。一旦我们检索到 3 个相关行,我们就会转到右侧的“部门”表以查找部门 ID 的实际值(111、119、181)。现在我们知道 Alice 属于 4Future、P0815 和 A42 部门。

在上面的图版本中,我们为 Alice 创建了一个单独的节点,标签为“人员”。Alice 属于 3 个不同的部门,因此我们为每个部门创建了一个节点,并带有“部门”标签。要找出 Alice 属于哪些部门,我们会在图中搜索 Alice 的节点,然后遍历从 Alice 到她连接的部门节点的所有 BELONGS_TO 关系。这就是我们所需要的——一次单跳,不涉及任何查找。

有关此主题的更多信息,请参阅数据建模部分

数据存储和检索

使用 SQL 查询关系型数据库非常简单——SQL 是一种声明式查询语言,既可以在数据库工具中轻松进行即席查询,也可以从应用程序代码中进行特定用例的查询。即使是对象关系映射器 (ORM) 也会在底层使用 SQL 与数据库通信。

图数据库有类似的东西吗?是的!

Cypher®,Neo4j 的声明式图查询语言,建立在 SQL 的基本概念和子句之上,但具有许多额外的图特定功能,使其易于使用您的图模型。

如果您曾尝试编写包含大量连接的 SQL 语句,您会发现由于 SQL 语法中的所有技术噪音,您很快就会看不清查询实际做了什么。在 Cypher 中,语法保持简洁并专注于领域组件及其之间的连接,更直观、更清晰地表达查找或创建数据的模式。基本模式匹配之外的其他子句与 SQL 非常相似,因为 Cypher 是基于其前身语言的基础构建的。

我们将在即将发布的指南中介绍 Cypher 查询语言语法,但让我们先看一个简短的示例,了解 SQL 查询与 Cypher 查询有何不同。在我们上面数据建模示例的组织领域中,一个列出 IT 部门员工的 SQL 语句会是什么样子,以及它与 Cypher 语句有何不同?

SQL 语句
SELECT name FROM Person
LEFT JOIN Person_Department
  ON Person.Id = Person_Department.PersonId
LEFT JOIN Department
  ON Department.Id = Person_Department.DepartmentId
WHERE Department.name = "IT Department"
Cypher 语句
MATCH (p:Person)-[:WORKS_AT]->(d:Dept)
WHERE d.name = "IT Department"
RETURN p.name

您可以在即将发布的关于Cypher 查询语言以及从 SQL 过渡到 Cypher 的章节中找到更多关于 Cypher 语法的信息。

从关系型到图的过渡 - 实践篇

如果您决定将数据从关系型数据库迁移到图数据库,将您的应用程序过渡到使用 Neo4j 的步骤实际上非常简单。您可以像连接其他数据库一样,使用专为您的技术栈或编程语言设计的驱动程序或连接器库连接到 Neo4j。感谢 Neo4j 及其社区,现在有 Neo4j 驱动程序,它们模仿了几乎所有流行编程语言的现有数据库驱动程序惯用法和方法。

例如,Neo4j JDBC 驱动程序会这样使用来查询数据库中John 的部门

Connection con = DriverManager.getConnection("jdbc:neo4j://:7474/");

String query =
    "MATCH (:Person {name:{1}})-[:EMPLOYEE]-(d:Department) RETURN d.name as dept";
try (PreparedStatement stmt = con.prepareStatement(QUERY)) {
    stmt.setString(1,"John");
    ResultSet rs = stmt.executeQuery();
    while(rs.next()) {
        String department = rs.getString("dept");
        ....
    }
}

更多信息,您可以访问我们的构建应用程序页面,了解如何使用不同的编程语言连接到 Neo4j。

© . All rights reserved.