Skip to main content

NoSQL-Graph-Neo4j

Neo4j

也支持OLTP之类的应用, 但对图表示方式进行了特殊的优化

dbms: 一般都有两层: 一是process engine, 生成查询计划; 二是storage engine, 执行文件读写

为什么需要图数据库: relational db lack relational support

正向查询需要多次join, 且反向追溯可能更难做

举例: 两张表 person 和 friendship

person: | id | person
friendship: | id | person_id | friend_id

需要找A的所有朋友

select p1.person from 
person p1 join friendship on p1.id = friendship.person_id
join person p2 on p2.id = frienship.friend_id
where p2.person="A"

需要两次join

找所有和A是朋友的人(假设朋友关系是单向的,或者改成A的关注和关注A的人), 还是两次join, 并且如果表再多起来, 反向容易先join大表达成复杂度爆炸

其他更复杂的需求 好友的好友 等, join次数还要增加, 最后不可忍受

例如 一个人买过哪些东西, 4表join user, order, orderItem, product

mongo呢?如果是嵌套表示, 正向是ok的, 嵌套打开; 但反向就寄了, 等同于json的数组里面以一个嵌套的很深attribute做filter, 只能做全表扫描, 并且空间上也有问题; 如果是引用表示, 和rdbms就差不多了

图db:

  • 边就是“索引”, 并不需要全表扫描, 按边一直走就行

  • 自然的表达多种关系, 不需要为每一种关系开一个表, 可以方便地做多关系联查

  • 方便做反向查询, 正向是对结点的所有出边引用, 反向就是所有入边

querying in graph: cypher

以机房,机架物理机,server, app,db, load balancer这几个概念为例

sql模型

image-20241124161857070

如果要找“这个user使用哪个load balancer”需要5次join

但是图的模型类似下图

image-20241124162000069

Test Graph Model When a user reports a problem, we can limit the physical fault-finding to problematic network elements between the user and the application and the application and its dependencies.

In our graph we can find the faulty equipment with the following query:

*MATCH (user:User)-[1..5]-(asset:Asset) WHERE user.name = 'User 3' AND asset.status = 'down' RETURN DISTINCT asset

This allows us to match paths such as:

> (user)-[:USER_OF]->(app)
> (user)-[:USER_OF]->(app)-[:USES]->(database)
> (user)-[:USER_OF]->(app)-[:USES]->(database)-[:SLAVE_OF]->(another-database)
> (user)-[:USER_OF]->(app)-[:RUNS_ON]->(vm)
> (user)-[:USER_OF]->(app)-[:RUNS_ON]->(vm)-[:HOSTED_BY]->(server)
> (user)-[:USER_OF]->(app)-[:RUNS_ON]->(vm)-[:HOSTED_BY]->(server)-[:IN]->(rack)
> (user)-[:USER_OF]->(app)-[:RUNS_ON]->(vm)-[:HOSTED_BY]->(server)-[:IN]->(rack) <-[:IN]-(load-balancer)

image-20241124162319655

neo4j

  • 可以以单独的服务跑
  • 可以嵌入式, 包进spring进程
  • 可以集群, 进行图的分割存储

怎么存这种高度变长的东西的?双向链表

节点的属性和边都是一个链表,节点自己只存链表入口和边入口

边存: src, dst;src节点的前一条边,后一条边; dst节点的前一条边,后一条边

image-20241124170029827

Neo4j in java, spring data整合, api类似sql

图计算

image-20241124170446219