1. Why Graph DB?
N 度人脉问题
社交网络应用中,基于直接好友关系(t_user_friend(user, friend)),如何构建用户的 N 度人脉?
1 度人脉:SELECT uf.friend FROM t_user_friend AS uf WHERE uf.user = ?
2 度人脉:SELECT uf2.friend FROM t_user_friend AS uf1 INNER JOIN t_user_friend AS uf2 ON uf1.friend = uf2.user WHERE uf1.user = ?
3 度人脉:SELECT uf3.friend FROM t_user_friend AS uf1 INNER JOIN t_user_friend AS uf2 ON uf1.friend = uf2.user INNER JOIN t_user_friend AS uf3 ON uf2.friend = uf3.user WHERE uf1.user = ?
......
在数据集包括 100 万人,每人约有 50 个朋友时实验结果如下:
从试验数据看,传统的关系型数据库在处理数据关联上显得力不从心。从哲学上看世间万物均有联系,不存在孤立的事物,我们无法回避,NoSQL能成为救星吗?
NoSQL 的种类
键值(key/value)数据库
列存储数据库
文档型数据库
图数据库
没错,图数据库就是天生用来解决联系的,使用最主流的图数据库 Neo4j 处理上面的 N 度人脉问题,与 MySQL 性能对比如下:
由于人类社会的各领域无处不存在联系,图数据库作为唯一能很好解决关联问题的数据库,得到了广泛应用:
社交领域:Facebook, Twitter,Linkedin用它来管理社交关系,实现好友推荐
零售领域:eBay,沃尔玛使用它实现商品实时推荐,给买家更好的购物体验
金融领域:摩根大通,花旗和瑞银等银行在用图数据库做风控处理
汽车制造领域:沃尔沃,戴姆勒和丰田等顶级汽车制造商依靠图数据库推动创新制造解决方案
电信领域:Verizon, Orange和AT&T 等电信公司依靠图数据库来管理网络,控制访问
酒店领域:万豪和雅高酒店等顶级酒店公司使用图数据库来管理复杂且快速变化的库存
2. 带标签的属性图模型
(1)节点
节点是主要的数据元素
节点通过关系连接到其他节点
节点可以具有一个或多个属性(即,存储为键/值对的属性)
节点有一个或多个标签,用于描述其在图表中的作用
(2)关系
关系连接两个节点
关系是方向性的
节点可以有多个甚至递归的关系
关系可以有一个或多个属性(即存储为键/值对的属性)
(3)属性
属性是命名值,其中名称(或键)是字符串
属性可以被索引和约束
可以从多个属性创建复合索引
(4)标签
标签用于将节点分组
一个节点可以具有多个标签
对标签进行索引以加速在图中查找节点
本机标签索引针对速度进行了优化
3. Cypher 图查询语言
Cypher是 Neo4j 的图形查询语言,允许用户存储和检索图形数据库中的数据。
举例,我们要查找 Joe 的所以二度好友:
查询语句如下:
MATCH
(person:Person {name:"Joe"})-[:KNOWS]->(friend:Person)-[:KNOWS]->
(foaf:Person)
WHERE
NOT (person)-[:KNOWS]->(foaf)
RETURN
foaf
Joe认识Sally,Sally认识Anna。 Bob被排除在结果之外,因为除了通过Sally成为二级朋友之外,他还是一级朋友。
4. 数据存储
数据存储主要分为节点、关系、节点或关系上属性这三类数据存储,这些数据也可以通过Lucene进行存储检索。
节点(指向联系和属性的单向链表,neostore.nodestore.db):第一个字节,表示是否被使用的标志位,后面4个字节,代表关联到这个节点的第一个关系的ID,再接着的4个字节,代表第一个属性ID,后面紧接着的5个字节是代表当前节点的标签,指向该节点的标签存储,最后一个字符作为保留位。
联系(双向链表,neostore.relationshipstore.db):第一个字节,表示是否被使用的标志位,后面4个字节,代表起始节点的ID,再接着的4个字节,代表结束节点的ID,然后是关系类型占用5个字节,然后依次接着是起始节点的上下联系和结束节点的上下联系,关系的最近属性ID,以及一个指示当前记录是否位于联系链的最前面。通过节点的前后关系形成双向链表,可以快速搜索到节点所有相关的边。
属性(neostore.propertystore.db)也是固定大小,每个属性记录包括4个属性块(一个属性记录最多容纳4个属性)和指向属性链中下一个属性的ID.。属性记录包括属性类型和指向属性索引文件的指针(neostore.propertysotre.db.index)。同时属性记录中可以内联和动态存储,在属性值存储占用小时,会直接存储在属性记录中,对于大属性值,可以分别存储在动态字符存储(neostore.propertysotre.db.strings)和动态数组存储(neostore.propertysotre.db.arrays)中,由于动态记录同样由记录大小固定的记录链表组成,因此大字符串和大数组会占据多个动态记录。
举个例子:
5. 图数据库排名
根据 DB-Engines 最新发布的图数据库排名,Neo4j 仍然大幅领先排在第一位