图数据库入门教程(一)简单理解图数据库
以下内容是个人的理解,一家之言,可能误导,但能入门
为什么会有图数据库?
作为研发,我们接触最多的当属关系型数据库:Mysql、Oracle,还有一些非关系型数据库:MongoDB、Redis等,再广泛一些我们还接触过搜索引擎:elasticsearch、solr等。
我们知道,每种技术都有它适用的场景,Mysql擅长处理一致性要求高长期持久化并有简单查询的场景,Redis擅长处理读多写少,并发量大,数据准确性要求没那么高的场景,elasticsearch擅长处理全文查找的场景。那图数据库解决的什么场景?-复杂的数据关系查询。
上图是thnkerpop官网列出的一个关系查询的对比,左侧是图数据库的查询,右侧是mysql的查询。抛开具体的业务,只看上面的语句我们会发现mysql的查询语法复杂,关联表多,性能自不必说,并不是Mysql不好用,而是这不是它擅长处理的场景,就好比它不擅长全文查找一样。而图数据库恰恰是为这种场景而生的。
这个一个图数据库厂商用传统关系型数据库 MySQL 跟图数据库 Neo4j 的查询性能对比 ,在一个包含 100 万人、每人约有 50 个朋友的社交网络里找最大深度为 5 的朋友的朋友,实验结果表明多跳查询中图数据库优势明显(见图 2)。
图 1
一个场景了解图数据库
我们分别用mysql和图数据库进行建模,进行一个关系查询,以更好的了解它们的区别。
我们有一些企业:华为、苹果、OPPO、VIVO、小米、三星等,他们之间的关联关系是:竞争
用mysql进行建模
- 企业表
字段 | 备注 | |
---|---|---|
id | ||
company_name | 企业名称 |
2.竞争关系表
字段 | 备注 | |
---|---|---|
source_company_id | a公司 | |
target_company_id | a公司竞争的公司id |
插入数据,大概关系是这样
- 查询华为的竞争对手,你能写出sql
SELECT *
FROM company
WHERE id IN (
SELECT target_company_id
FROM comp_rel, company
WHERE comp_rel.`source_company_id` = company.`id`
AND company.`company_name` = '华为'
)
- 查询华为竞争对手的竞争对手,即二级竞争对手,你思索再三,写了出来
SELECT company.company_name
FROM comp_rel, company
WHERE comp_rel.`target_company_id` = company.id
AND `source_company_id` IN (
SELECT id
FROM company
WHERE id IN (
SELECT target_company_id
FROM comp_rel, company
WHERE comp_rel.`source_company_id` = company.`id`
AND company.`company_name` = '华为'
)
)
- 查询华为的一级和二级竞争对手
- 查询华为的三级竞争对手
- ...
可以看出来,sql不好写,即使写出来,也不敢上线😅
用图数据库进行建模
在建模前我们先理解两个概念,『顶点』和『边』
这里的顶点,我们可以理解为数据实体,比如说对应企业表的一个条数据,边就是企业之间的关系,对应竞争表的一条数据。
顶点的属性就是企业表的字段
边的属性就是竞争表的字段
- 在图数据库中创建公司(这里你不需要知道用的是什么图数据库,写的是什么语法,也不需要操作,只需简单理解)
g.addV('company').property('name','华为')
g.addV('company').property('name','苹果')
g.addV('company').property('name','三星')
g.addV('company').property('name','小米')
g.addV('company').property('name','OPPO')
g.addV('company').property('name','VIVO')
g.addV('company').property('name','格力')
- 创建公司的竞争关系
g.V().has("company","name","华为").addE("comp").to(__.V().has("company","name","小米"))
g.V().has("company","name","华为").addE("comp").to(__.V().has("company","name","三星"))
g.V().has("company","name","华为").addE("comp").to(__.V().has("company","name","VIVO"))
g.V().has("company","name","三星").addE("comp").to(__.V().has("company","name","苹果"))
g.V().has("company","name","OPPO").addE("comp").to(__.V().has("company","name","VIVO"))
g.V().has("company","name","OPPO").addE("comp").to(__.V().has("company","name","格力"))
3.查询华为竞争对手
g.V('华为').out()
- 查询华为二级竞争对手
g.V().has("company","name","华为").out().out()
为什么只有苹果出来了?OPPO呢?这个疑问留在心里,后面会讲
- 查询华为三级竞争对手
g.V().has("company","name","华为").out().out().out()
# 也可以这么写
g.V().has("company","name","华为").repeat(out()).times(3)
- 查询华为1、2、3级竞争对手
g.V().has("company","name","华为").repeat(out().aggregate('a')).times(3).cap('a')
怎么样,有没有感觉图数据库就是为查关系而生的,处理复杂的问题得心应手,当得上"优雅"二字,岂止"优雅",性能方便也是出类拔萃,目前主流的数据库支持的数据规模都在亿级以上,感受一下它们的压迫力吧!