图数据库Neo4j数据建模系列(三) — 关系与图模型的转变

图数据库Neo4j数据建模系列(三) — 关系与图模型的转变

自80年代以来,关系数据库一直是软件应用程序的主力军,并且一直沿用至今。它们将高度结构化的数据存储在具有特定类型的行和列的表中,关系数据库要求开发人员和应用程序严格构造其应用程序中使用的数据。
在关系数据库中,通过外键引用主键属性来执行对其他行和表的引用,连接是在查询时通过匹配连接表中所有行的主键和外键来计算的。这些操作需要大量计算并占用大量内存,成本随着数据量和复杂度成指数级增加。
模型发生多对多关系时,必须引入一个JOIN表(或关联表)来保存两个参与表的外键,从而进一步增加 JOIN 操作的成本。下图显示了通过创建一个Person-Department联接表将一个Person(从Person表)连接到Department(在Department表中)的概念,该表在一个列中包含该人员的ID和该ID中相关部门的ID。
如您所见,这使理解连接变得非常麻烦,因为您必须知道人员ID和部门ID(执行其他查找才能找到它们)才能知道哪个人连接到哪个部门。这些类型的昂贵联接操作通常通过对数据进行非规范化以减少必要的联接数来解决,从而破坏了关系数据库的数据完整性。

关系模型

尽管并非每种用例都适合这种严格的数据模型,但由于缺乏可行的替代方案以及对关系数据库的广泛支持,使得替代模型很难进入主流。但是,NoSQL时代的来临,满足了用户和企业的一些特定需求,但仍然缺少数据之间连接的重要性,这就是图数据库的诞生原因,旨在为当今生活的互联世界中提供最大的优势。

一、差异


与其他数据库管理系统不同,关系在图数据模型中与数据本身同等重要。这意味着我们不需要使用特殊属性(例如外键,map-reduce)来推断实体之间的连接。
通过将节点和关系组装到连接的结构中,图数据库使我们能够构建简单的模型,紧密地映射到我们的问题领域。数据与现实世界中的形式非常相似-小型、规范化但联系紧密的实体,这使您可以从任何可以想象的兴趣点查询和查看数据,从而支持许多不同的用例。
图数据库模型中的每个节点(实体或属性)直接且物理上包含关系记录的列表,这些关系记录表示与其他节点的关系。这些关系记录按类型和方向进行组织,并且可以包含其他属性。每当您运行与JOIN操作等效的操作时,图数据库都会使用此列表,直接访问连接的节点,从而无需进行昂贵的搜索和匹配计算。
这种将关系预先物化到数据库结构中的设计使Neo4j可以提供比其他形式高几个数量级的性能,尤其是对于大量连接的查询,性能优势非常明显。

1、数据模型差异
正如您可能从上面讨论的结构差异中想象的那样,关系数据和图数据的数据模型有很大的不同。与使用传统的关系数据库或其他NoSQL数据库生成的数据模型相比,直接的图结构可创建更加简单和更具表达力的数据模型。
如果您习惯使用关系数据库进行建模,请记住精心设计的标准化实体关系图的简单性和美感-一种简单易懂的模型,您可以快速与同事和领域专家一起白板。图就是这样-一个清晰的域模型,专注于您要有效支持的用例。
让我们比较两个数据模型,以显示关系和图之间的结构差异。

关系–人员和部门表

在上面的关系示例中,我们在左侧的Person表(可能数百万行)中搜索用户Alice及其人员ID 815。然后,在Person-Department表(橙色中间表)中查找所有引用Alice的人员ID(815)的行。检索到3条相关的行后,我们将转到右侧的“Department”表以搜索部门ID(111、119、181)。现在我们知道 Alice 是4Future、P0815和A42部门的成员。

图–Alice和3个部门作为节点

在上述图模型,我们为Alice提供了一个带有 Person 标签的单个节点。Alice 属于3个不同的部门,因此我们为每个部门创建一个节点,并带有 Department 标签。要找出 Alice 属于哪个部门,我们将在图中搜索Alice的节点,然后遍历Alice的所有 BELONGS_TO 关系以找到她所连接的 Department 节点。

2、数据存储与检索
SQL是一种声明性查询语言,使用SQL工具可以轻松地查询关系数据库,该查询语言既可以在数据库工具中方便地进行查询,也可以从应用程序代码中进行针对用例的查询。甚至对象关系映射器(ORM)也在后台使用SQL与数据库进行通信。
图数据库有类似的语言吗?是!
Cypher 是 Neo4j 的声明性图查询语言,它基于SQL的基本概念和子句构建,但是具有许多其他特定于图的功能,可以轻松使用图模型。
如果您曾经尝试编写带有大量联接的SQL语句,那么您会知道,由于SQL语法中的所有技术问题,您很快就会忽略了查询的实际作用。在Cypher中,语法保持简洁,重点放在域组件及其之间的连接上,表达了一种模式,以更直观、更清晰地查找或创建数据。基本模式匹配之外的其他子句看起来与SQL非常相似,因为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

二、建模:从关系到图

如果您熟悉具有表、列、关系基数和其他组件的关系数据模型,则图数据建模似乎并不完全陌生。数据模型的设计仍然需要基于访问、查询、性能预期和业务逻辑的要求。但是,图数据模型的结构略有不同。
作为简单概述,请记住,关系数据库依靠索引查找和表联接来连接不同的实体。这很快就成为性能问题,尤其是当有多个表联接,表中有数百万行或通过子查询遍历各个级别的复杂查询时。

  • 表到节点标签 –关系模型中的每个实体表都成为图模型中节点上的标签。
  • 行到节点 –关系实体表中的每一行都成为图中的一个节点。
  • 列到节点的属性 –关系表上的列(字段)成为图中的节点属性。
  • 业务主键 –删除技术主键,保留业务主键。
  • 添加约束/索引 –为业务主键添加唯一约束,为频繁查找属性添加索引。
  • 关系的外键–用关系替换另一个表的外键,然后将其删除。
  • 无默认值 –删除具有默认值的数据,无需存储这些值。
  • 清理数据 –必须将非规范化表中的重复数据拉到单独的节点中以获得更清晰的模型。
  • 数组的索引列–索引列名(例如email1,email2,email3)可能表示数组属性。
  • 将表联接到关系 –将联接表转换为关系,这些表上的列成为关系属性


尽管这两个模型具有相似之处,例如通过使用表结构或标签对数据进行分类,但是图模型并未将数据限制在预定义且严格的表/列布局中。

三、组织域数据模型

为了给我们一个实践的机会,我们将使用一个标准的组织域,并演示如何在关系数据库和图数据库中对它进行建模。为了给自己带来更多挑战,请尝试自行创建图数据模型,然后查看其排列紧密程度!

组织域–关系模型

具体的模型转换过程如下:

1、首先,我们可以按主域表对表进行分类,并按颜色对关联实体表进行分类。然后,我们可以将表名转换为节点标签。在这种情况下,ProjectPersonDepartmentOrganization成为我们的图模型标签。
2、表上的行成为它们自己的节点,而这些行中的列成为这些节点上的属性。例如,“Person”表上的行将成为一个节点,并以您的姓名和出生日期作为节点上的属性。任何允许多个相似值的索引列都将成为一个数组(例如skill1,skill2,skill3列转换为节点上数组属性中存储的三个值)。
3、如果有任何技术主键(换句话说,创建主键只是为了使行唯一。例如,如果有多个具有相同标题的项目,则为project_id),然后删除这些主键并仅保留所需的属性用于业务需求。您还需要为业务主键添加唯一约束,以确保数据库不允许重复。
4、有助于关系联接查找的外键会转换为关系,因为它们显示了节点之间的链接。连接表(或关联实体表)也变为关系,所有连接表列都移至关系属性。由于仅在Neo4j中存储所需的属性,因此不需要存储null和空值,因此可以删除在关系模型中可能创建的任何默认值。
5、最后,简单起见,创建用于规范化表或取消规范化的任何重复数据都需要删除,因为在图中是不需要的。
完成此过程后,您的图数据模型应类似于下图。

组织域–图模型


在开始导入数据之前,对图模型有基本的了解是很重要的,因为随着需求的变化,对模型进行丰富或调整变得更加容易。

图数据库Neo4j数据建模系列:

图数据库Neo4j数据建模系列(一) — 数据建模基础
图数据库Neo4j数据建模系列(二) — 数据建模准则
图数据库Neo4j数据建模系列(三) — 关系与图模型的转变
图数据库Neo4j数据建模系列(四) — 图数据建模
图数据库Neo4j数据建模系列(五) — 建模技巧及模型重构

至此,数据建模的相关概念及技巧就介绍完了,后续将基于一些实际的业务场景共同探讨图数据建模,敬请期待。

近期也在尝试 OrientDB 数据迁移到Neo4j,有时间的话,我也会更新一些迁移细节。

编辑于 2020-05-29 10:57