关系

图数据库最重要的特征之一就是它们如何管理关系。许多用户从MongoDB转到OrientDB,因为它更有效的支持关系的处理。

关系型数据库中的关系

大多数开发人员熟悉关系数据库中的关系模型,例如MySQL和MS-SQL。30多年的统治地位,让大家长期以为这是处理关系的最好方式。相对来说,图数据库提供了一个更加先进的方式处理关系。

例如,你需要建立CustomerAddress两个表的关系。

1对1关系

关系型数据库在表Customeraddress列中存储目标记录的值,也就是外键。外键指向Address表关联记录的主键。

RDBMS 1-to-1

如果你想访问叫Luca的客户的地址,在关系数据库,例如MySQL中,查询如下:

mysql> SELECT B.location FROM Customer A, Address B
          WHERE A.name='Luca' AND A.address=B.id;

这里使用了JOIN,两个表联合在一起形成结果。数据库每次获取关系都要执行JOIN

1对多关系

关系型数据库没有集合的概念,所以表Customer不能有多个外键。唯一的方式就是将外键放到表Address里面。

RDBMS 1-to-N

例如,返回一个客户的所有地址,需要下面的查询:

mysql> SELECT B.location FROM Customer A, Address B
          WHERE A.name='Luca' AND B.customer=A.id;

多对多关系

最复杂的情况就是多对多关系。处理这种联系,关系数据需要一张独立的表,中间表关联表CustomerAddress。这样在运行时,就会导致双重JOIN

RDBMS Many-to-Many

例如,需要返回客户Luca的所有地址, 需要如下查询:

mysql> SELECT B.location FROM Customer A, CustomerAddress B, Address C
          WHERE A.name='Luca' AND B.id=A.id AND B.address=C.id;

理解JOIN

在文档和关系数据库系统中,数据越多,数据库的响应和JOIN操作越耗时。

对于关系数据库,每次查询都会计算关系,需要O(log N / block_size)(使用B-Tree树索引主键,block_size表示B-Tree一层的数量)的时间复杂度。 OrientDB直接使用物理连接指向记录,而且只在边创建的时候记录一次,时间复杂度为O(1)

OrientDB中,遍历的速度不受数据库数量级的影响。无论是一条记录还是数千亿条,都保持常数级的响应。这在大数据的时候,是非常关键的因素。

对于每条记录来说,每次查询的时候都要去搜索一次,成本是很高的。关系数据库中第一种解决方案就是采用索引,但是索引会减慢INSERT, UPDATEDELETE的速度。除此之外,索引还额外占用硬盘和内存的空间,还要考虑索引是不是真的能加快搜索。

索引和JOIN

在数据库行业,有很多索引算法,关系和Nosql数据库最常用的就是B+ 树

平衡树工作方式类似。例如,查找Luca: 经过5次跳跃,记录就找到了。

RDBMS Indexes

在小的数据库还行,如果几百万或者几十亿条记录,灾难就来临了。数据库经过很多很多次跳跃才能找到Luca。而且,每条记录都要执行JOIN操作。 如图: 关联四个表,几千条记录,JOIN操作需要执行几百万次。

OrientDB的关系

OrientDB中没有JOIN而是使用LINKLINK在源记录中存储目标记录的Record ID。类似于,在内存中存储了两个对象的指针。

当你需要Invoice连接Customer时,就像保持了一个Customer的指针在 Invoice属性里。就如同你的数据库被保存在内存中:一个艾字节级别的内存。

关系的类型

在1对N的关系中,OrientDB使用RID的集合来解决,和内存中管理对象一样。

OrientDB支持很多种的关系:

  • LINK 关联1条记录。
  • LINKSET 关联多条记录。类似于Java的Set,集合中RID唯一且无需排列。
  • LINKLIST 关联多条记录。类似Java的List,RID有序可重复。
  • LINKMAP 关联多条记录,每个RID对应一个key。类似于Java的Map<?,Record>