文档解读 | 关系型数据库查询语言 SQL 和图数据库查询语言 nGQL 对比
摘要:这篇文章将介绍图数据库 Nebula Graph 的查询语言 nGQL 和 SQL 的区别。
本文首发于 Nebula Graph 官方博客:https://nebula-graph.com.cn/posts/sql-vs-ngql-comparison/
虽然本文主要介绍 nGQL 和 SQL 的区别,但是我们不会深入探讨这两种语言,而是将这两种语言做对比,以帮助你从 SQL 过渡到 nGQL。
SQL (Structured Query Language) 是具有数据操纵和数据定义等多种功能的数据库语言,这种语言是一种特定目的编程语言,用于管理关系数据库管理系统(RDBMS),或在关系流数据管理系统(RDSMS)中进行流处理。
nGQL 是一种类 SQL 的声明型的文本查询语言,相比于 SQL, nGQL 为可扩展、支持图遍历、模式匹配、分布式事务(开发中)的图数据库查询语言。
概念对比
对比项 | SQL | nGQL |
---|---|---|
点 | \ | 点 |
边 | \ | 边 |
点类型 | \ | tag |
边类型 | \ | edge type |
点 ID | 主键 | vid |
边 ID | 复合主键 | 起点、终点、rank |
列 | 列 | 点或边的属性 |
行 | 行 | 点或边 |
语法对比
数据定义语言 (DDL)
数据定义语言(DDL)用于创建或修改数据库的结构,也就是 schema。
对比项 | SQL | nGQL |
---|---|---|
创建图空间(数据库) | CREATE DATABASE <database_name> | CREATE SPACE <space_name> |
列出图空间(数据库) | SHOW DATABASES | SHOW SPACES |
使用图空间(数据库) | USE <database_name> | USE <space_name> |
删除图空间(数据库) | DROP DATABASE <database_name> | DROP SPACE <space_name> |
修改图空间(数据库) | ALTER DATABASE <database_name> alter_option | \ |
创建 tags/edges | \ | CREATE TAG | EDGE <tag_name> |
创建表 | CREATE TABLE <tbl_name> (create_definition,...) | \ |
列出表列名 | SHOW COLUMNS FROM <tbl_name> | \ |
列出 tags/edges | \ | SHOW TAGS | EDGES |
Describe tags/edge | \ | DESCRIBE TAG | EDGE <tag_name | edge_name> |
修改 tags/edge | \ | ALTER TAG | EDGE <tag_name | edge_name> |
修改表 | ALTER TABLE <tbl_name> | \ |
索引
对比项 | SQL | nGQL |
---|---|---|
创建索引 | CREATE INDEX | CREATE {TAG | EDGE} INDEX |
删除索引 | DROP INDEX | DROP {TAG | EDGE} INDEX |
列出索引 | SHOW INDEX FROM | SHOW {TAG | EDGE} INDEXES |
重构索引 | ANALYZE TABLE | REBUILD {TAG | EDGE} INDEX <index_name> [OFFLINE] |
数据操作语言(DML)
数据操作语言(DML)用于操作数据库中的数据。
对比项 | SQL | nGQL |
---|---|---|
插入数据 | INSERT IGNORE INTO <tbl_name> [(col_name [, col_name] ...)] {VALUES | VALUE} [(value_list) [, (value_list)] | INSERT VERTEX <tag_name> (prop_name_list[, prop_name_list]) {VALUES | VALUE} vid: (prop_value_list[, prop_value_list]) INSERT EDGE <edge_name> ( <prop_name_list> ) VALUES | VALUE <src_vid> -> <dst_vid> [@<rank> ] : ( <prop_value_list> ) |
查询数据 | SELECT | GO, FETCH |
更新数据 | UPDATE <tbl_name> SET field1=new-value1, field2=new-value2 [WHERE Clause] | UPDATE VERTEX <vid> SET <update_columns> [WHEN <condition> ] UPDATE EDGE <edge> SET <update_columns> [WHEN <condition> ] |
删除数据 | DELETE FROM <tbl_name> [WHERE Clause] | DELETE EDGE <edge_type> <vid> -> <vid> [@<rank> ] [, <vid> -> <vid> ...] DELETE VERTEX <vid_list> |
拼接数据 | JOIN | | |
数据查询语言(DQL)
数据查询语言(DQL)语句用于执行数据查询。本节说明如何使用 SQL 语句和 nGQL 语句查询数据。
SELECT [DISTINCT] select_expr [, select_expr] ... [FROM table_references] [WHERE where_condition] [GROUP BY {col_name | expr | position}] [HAVING where_condition] [ORDER BY {col_name | expr | position} [ASC | DESC]]
GO [[<M> TO] <N> STEPS ] FROM <node_list> OVER <edge_type_list> [REVERSELY] [BIDIRECT] [WHERE where_condition] [YIELD [DISTINCT] <return_list>] [| ORDER BY <expression> [ASC | DESC]] [| LIMIT [<offset_value>,] <number_rows>] [| GROUP BY {col_name | expr | position} YIELD <col_name>] <node_list> | <vid> [, <vid> ...] | $-.id <edge_type_list> edge_type [, edge_type ...] <return_list> <col_name> [AS <col_alias>] [, <col_name> [AS <col_alias>] ...]
数据控制语言(DCL)
数据控制语言(DCL)包含诸如 GRANT
和 REVOKE
之类的命令,这些命令主要用来处理数据库系统的权限、其他控件。
对比项 | SQL | nGQL |
---|---|---|
创建用户 | CREATE USER | CREATE USER |
删除用户 | DROP USER | DROP USER |
更改密码 | SET PASSWORD | CHANGE PASSWORD |
授予权限 | GRANT <priv_type> ON [object_type] TO <user> | GRANT ROLE <role_type> ON <space> TO <user> |
删除权限 | REVOKE <priv_type> ON [object_type] TO <user> | REVOKE ROLE <role_type> ON <space> FROM <user> |
数据模型
查询语句基于以下数据模型:
RDBMS 关系结构图
Nebula Graph 最小模型图
本文将使用 NBA 数据集。该数据集包含两种类型的点,也就是两个标签,即 player
和 team
;两种类型的边,分别是 serve
和 follow
。
在关系型数据管理系统中(RDBMS)中,我们用表来表示点以及与点相关的边(连接表)。因此,我们创建了以下表格:player
、team
、serve
和 follow
。在 Nebula Graph 中,基本数据单位是顶点和边。两者都可以拥有属性,相当于 RDBMS 中的属性。
在 Nebula Graph 中,点之间的关系由边表示。每条边都有一种类型,在 NBA 数据集中,我们使用边类型 serve
和 follow
来区分两种类型的边。
示例数据
在 RDBMS 插入数据
首先,让我们看看如何在 RDBMS 中插入数据。我们先创建一些表,然后为这些表插入数据。
CREATE TABLE player (id INT, name VARCHAR(100), age INT); CREATE TABLE team (id INT, name VARCHAR(100)); CREATE TABLE serve (player_id INT, team_id INT, start_year INT, end_year INT); CREATE TABLE follow (player_id1 INT, player_id2 INT, degree INT);
然后插入数据。
INSERT INTO player VALUES (100, 'Tim Duncan', 42), (101, 'Tony Parker', 36), (102, 'LaMarcus Aldridge', 33), (103, 'Rudy Gay',32), (104, 'Marco Belinelli', 32), (105, 'Danny Green', 31), (106, 'Kyle Anderson', 25), (107, 'Aron Baynes', 32), (108, 'Boris Diaw', 36), (109, 'Tiago Splitter', 34), (110, 'Cory Joseph', 27); INSERT INTO team VALUES (200, 'Warriors'), (201, 'Nuggets'), (202, 'Rockets'), (203, 'Trail'), (204, 'Spurs'), (205, 'Thunders'), (206, 'Jazz'), (207, 'Clippers'), (208, 'Kings'); INSERT INTO serve VALUES (100,200,1997,2016), (101,200,1999,2010), (102,200,2001,2005), (106,200,2000,2011), (107,200,2001,2009), (103,201,1999,2018), (104,201,2006,2015), (107,201,2007,2010), (108,201,2010,2016), (109,201,2011,2015), (105,202,2015,2019), (109,202,2017,2019), (110,202,2007,2009); INSERT INTO follow VALUES (100,101,95), (100,102,91), (100,106,90), (101,100,95), (101,102,91), (102,101,75), (103,102,70), (104,103,50), (104,105,60), (105,104,83), (105,110,87), (106,100,88), (106,107,81), (107,106,92), (107,108,97), (108,109,95), (109,110,78), (110,109,72), (110,105,85);
在 Nebula Graph 插入数据
在 Nebula Graph 中插入数据与上述类似。首先,我们需要定义好数据结构,也就是创建好 schema。然后可以选择手动或使用 Nebula Graph Studio (Nebula Graph 的可视化工具)导入数据。这里我们手动添加数据。
在下方的 INSERT
插入语句中,我们向图空间 NBA 插入了球员数据(这和在 MySQL 中插入数据类似)。
INSERT VERTEX player(name, age) VALUES 100: ('Tim Duncan', 42), 101: ('Tony Parker', 36), 102: ('LaMarcus Aldridge', 33), 103: ('Rudy Gay', 32), 104: ('Marco Belinelli', 32), 105: ('Danny Green', 31), 106: ('Kyle Anderson', 25), 107: ('Aron Baynes', 32), 108: ('Boris Diaw', 36), 109: ('Tiago Splitter', 34), 110: ('Cory Joseph', 27);
考虑到篇幅限制,此处我们将跳过插入球队和边的重复步骤。你可以点击此处下载示例数据亲自尝试。
增删改查(CRUD)
本节介绍如何使用 SQL 和 nGQL 语句创建(C)、读取(R)、更新(U)和删除(D)数据。
插入数据
mysql> INSERT INTO player VALUES (100, 'Tim Duncan', 42); nebula> INSERT VERTEX player(name, age) VALUES 100: ('Tim Duncan', 42);
查询数据
查找 ID 为 100 的球员并返回其 name
属性:
mysql> SELECT player.name FROM player WHERE player.id = 100; nebula> FETCH PROP ON player 100 YIELD player.name;
更新数据
mysql> UPDATE player SET name = 'Tim'; nebula> UPDATE VERTEX 100 SET player.name = "Tim";
删除数据
mysql> DELETE FROM player WHERE name = 'Tim'; nebula> DELETE VERTEX 121; nebula> DELETE EDGE follow 100 -> 200;
建立索引
返回年龄超过 36 岁的球员。
SELECT player.name FROM player WHERE player.age < 36;
使用 nGQL 查询有些不同,因为您必须在过滤属性之前创建索引。更多信息请参见 索引文档。
CREATE TAG INDEX player_age ON player(age); REBUILD TAG INDEX player_age OFFLINE; LOOKUP ON player WHERE player.age < 36;
示例查询
本节提供一些示例查询供您参考。
示例 1
在表 player
中查询 ID 为 100 的球员并返回其 name
属性。
SELECT player.name FROM player WHERE player.id = 100;
接下来使用 Nebula Graph 查找 ID 为 100 的球员并返回其 name
属性。
FETCH PROP ON player 100 YIELD player.name;
Nebula Graph 使用 FETCH
关键字获取特定点或边的属性。本例中,属性即为点 100 的名称。nGQL 中的 YIELD
关键字相当于 SQL 中的 SELECT
。
示例 2
查找球员 Tim Duncan 并返回他效力的所有球队。
SELECT a.id, a.name, c.name FROM player a JOIN serve b ON a.id=b.player_id JOIN team c ON c.id=b.team_id WHERE a.name = 'Tim Duncan'
使用如下 nGQL 语句完成相同操作:
CREATE TAG INDEX player_name ON player(name); REBUILD TAG INDEX player_name OFFLINE; LOOKUP ON player WHERE player.name == 'Tim Duncan' YIELD player.name AS name | GO FROM $-.VertexID OVER serve YIELD $-.name, $$.team.name;
这里需要注意一下,在 nGQL 中的等于操作采用的是 C 语言风格的 ==
,而不是SQL风格的 =
。
示例 3
以下查询略复杂,现在我们来查询球员 Tim Duncan 的队友。
SELECT a.id, a.name, c.name FROM player a JOIN serve b ON a.id=b.player_id JOIN team c ON c.id=b.team_id WHERE c.name IN (SELECT c.name FROM player a JOIN serve b ON a.id=b.player_id JOIN team c ON c.id=b.team_id WHERE a.name = 'Tim Duncan')
nGQL 则使用管道将前一个子句的结果作为下一个子句的输入。
GO FROM 100 OVER serve YIELD serve._dst AS Team | GO FROM $-.Team OVER serve REVERSELY YIELD $$.player.name;
您可能已经注意到了,我们仅在 SQL 中使用了 JOIN
。这是因为 Nebula Graph 只是使用类似 Shell 的管道对子查询进行嵌套,这样更符合我们的阅读习惯也更简洁。
参考资料
我们建议您亲自尝试上述查询语句,这将帮您更好地理解 SQL 和 nGQL,并节省您上手 nGQL 的学习时间。以下是一些参考资料:
作者有话说:Hi,Hi ,大家好,我是 Amber,Nebula Graph 的文档工程师,希望上述内容可以给大家带来些许启发。限于水平,如有不当之处还请斧正,在此感谢^^
喜欢这篇文章?来来来,给我们的 GitHub 点个 star 表鼓励啦~~ 🙇♂️🙇♀️ [手动跪谢]
交流图数据库技术?交个朋友,Nebula Graph 官方小助手微信:NebulaGraphbot 拉你进交流群~~
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
JVM系列之:Contend注解和false-sharing
简介 现代CPU为了提升性能都会有自己的缓存结构,而多核CPU为了同时正常工作,引入了MESI,作为CPU缓存之间同步的协议。MESI虽然很好,但是不当的时候用也可能导致性能的退化。 到底怎么回事呢?一起来看看吧。 false-sharing的由来 为了提升处理速度,CPU引入了缓存的概念,我们先看一张CPU缓存的示意图: CPU缓存是位于CPU与内存之间的临时数据交换器,它的容量比内存小的多但是交换速度却比内存要快得多。 CPU的读实际上就是层层缓存的查找过程,如果所有的缓存都没有找到的情况下,就是主内存中读取。 为了简化和提升缓存和内存的处理效率,缓存的处理是以Cache Line(缓存行)为单位的。 一次读取一个Cache Line的大小到缓存。 在mac系统中,你可以使用sysctl machdep.cpu.cache.linesize来查看cache line的大小。 在linux系统中,使用getconf LEVEL1_DCACHE_LINESIZE来获取cache line的大小。 本机中cache line的大小是64字节。 考虑下面一个对象: public class...
- 下一篇
5个规则,确保你的微服务优化运行
最近几年好像大家都开始对微服务着迷,与此同时单体架构也在慢慢淡出人们的视线。 当然,热门的趋势总是来来去去,而且它们所受到的关注往往被媒体夸大了,实际情况并不总是如此。不过,对于微服务来说,人们似乎已经达成共识,认为这个趋势会一直存在下去。这是有道理的。从概念的角度来说,微服务扩展了工程师们几十年来采用的相同原则。 一旦你开始使用微服务架构,也许你需要本文中提到的5个规则,帮助你成功运行它们。 微服务的另一面 关注点分离(SoC)是一项设计原则,规定软件的构建应根据 "关注点 "或总体功能来确定不同的部分,30多年来一直被用来决定如何构建技术。在单体应用中,它体现在典型的3层架构中的表现层、业务层和数据层的分离。 微服务采用了这个概念,并将其颠覆。它们将同一个应用程序以这样的方式分离出来,应用程序的单一代码库可以被分解并单独部署。这样做的好处是巨大的,但也是有代价的,通常体现在时间和金钱两方面的运维成本较高。除了将现有的应用程序过渡到容器所带来的巨大的前期投资之外,维护该应用程序也带来了新的挑战。 挑战1:似乎很难监控整体 虽然单体应用程序也有其自身的挑战,但在单体中回滚一个“坏”版本...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- 设置Eclipse缩进为4个空格,增强代码规范
- Mario游戏-低调大师作品
- MySQL8.0.19开启GTID主从同步CentOS8
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS8编译安装MySQL8.0.19
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- SpringBoot2整合Redis,开启缓存,提高访问速度
- CentOS关闭SELinux安全模块