关系
图数据库最重要的特征之一就是它们如何管理关系。许多用户从MongoDB转到OrientDB,因为它更有效的支持关系的处理。
关系型数据库中的关系
大多数开发人员熟悉关系数据库中的关系模型,例如MySQL和MS-SQL。30多年的统治地位,让大家长期以为这是处理关系的最好方式。相对来说,图数据库提供了一个更加先进的方式处理关系。
例如,你需要建立Customer
和Address
两个表的关系。
1对1关系
关系型数据库在表Customer
的address
列中存储目标记录的值,也就是外键。外键指向Address
表关联记录的主键。
如果你想访问叫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
里面。
例如,返回一个客户的所有地址,需要下面的查询:
mysql> SELECT B.location FROM Customer A, Address B
WHERE A.name='Luca' AND B.customer=A.id;
多对多关系
最复杂的情况就是多对多关系。处理这种联系,关系数据需要一张独立的表,中间表关联表Customer
和Address
。这样在运行时,就会导致双重JOIN
。
例如,需要返回客户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
, UPDATE
和DELETE
的速度。除此之外,索引还额外占用硬盘和内存的空间,还要考虑索引是不是真的能加快搜索。
索引和JOIN
在数据库行业,有很多索引算法,关系和Nosql数据库最常用的就是B+ 树。
平衡树工作方式类似。例如,查找Luca
: 经过5次跳跃,记录就找到了。
在小的数据库还行,如果几百万或者几十亿条记录,灾难就来临了。数据库经过很多很多次跳跃才能找到Luca
。而且,每条记录都要执行JOIN
操作。 如图: 关联四个表,几千条记录,JOIN
操作需要执行几百万次。
OrientDB的关系
OrientDB中没有JOIN
而是使用LINK
。LINK
在源记录中存储目标记录的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>
。