使用 SQL, GraphQL 和 PRQL 进行数据查询

2023-01-13 10:03:59 +08:00
 hongchaodeng

SQL 对大多数程序员来说都不陌生,但是 GraphQL 和 PRQL 对大多数程序员来说都是陌生的。本文将对三者进行对比介绍,方便大家在合适的业务场景进行选择。

SQL PRQL GraphQL
Query Y Y Y
Update Y N Y
Subscription N N Y

几点注意事项:

SQL

SQL 大家都不陌生,举一个根据 ID 查找用户的简单例子来说明一下,查询如下:

select * from user where id = 1000

数据库的工具可以说是最丰富的,如开发者都喜欢的 O/R 映射框架,进行数据更新,可以说是简单的不能再简单了,开发者完全不需要了解具体的 SQL 语法。 当然 O/R 框架在查询方面稍微有点弱,但是在数据库更新操作上,O/R 框架是非常强大的。

GraphQL

GraphQL 是是一种基于类型系统,面向数据的 API 查询语言。 让我们看一下上述 SQL 对应的 GraphQL 查询语言,如下:

{
  user(id: 1000) {
    name
    mobile
    birth
  }
}

很多同学将 GraphQL 和 HTTP REST API 进行对比,这里我们不做讨论,我们这里主要说明 GraphQL 查询语言的灵活性。

现在有非常多的工具可以为数据库添加 GraphQL 接入,非常简单。 我们都知道数据库连接是非常耗资源的,而 GraphQL over HTTP 则非常轻量级,这种方式在 Serverless 的场景中非常适合。

GraphQL 不足:从上述的样例中我们可以看出,对于一些复杂场景的查询,GraphQL 还是有点力不从心的,如果几个查询条件配合,这个时候 GraphQL 处理起来就比较难啦,要编写特定查询实现,这个和 REST API 实现也是一样的。

PRQL

PRQL 是一种用于转换数据的现代语言,其主要的特性就是基于数据的管道操作。让我们看一下上述 SQL 对应的 PRQL 查询语言,如下:

from user | filter id == 1000

可以说 PRQL 在查询方面更简单明了,可以说比数据库 select 更强都不为过。

我们都知道架构设计中有一个读写分离(CQRS)原则,当然数据库更新,你选择 SQL ,O/R 框架这些都没有问题。但是在 Query 方面,你可以选择 PRQL ,这样可以让你的数据查询更简单,同时支持快速 JSON 输出。

PRQL 可以被编译为 SQL ,这样就可以在任何数据库上操作,但是其他诸如 NoSQL 产品,PRQL 也更合适。如你想操作 MongoDB ,对应的查询命令如下:

db.inventory.find( {
     status: "A",
     $or: [ { qty: { $lt: 30 } }, { price: { $gt: 100 }  } ]
} )

如果换成 PRQL ,则如下:

from inventory
filter status = "A"
filter qty < 30 or price > 100

这两个谁更容易阅读和理解,我相信大家马上就有自己的答案。

此外 PRQL 还有一个非常强大的特性就是基于数据库的 dialect ,可以将 PRQL 编译为目标数据库的 SQL ,这样你只要关心更通用的 PRQL ,而不需要关注不同数据库的 SQL 差异,数据库的兼容完全不用担心。

回到 NoSQL 场景,虽然 PRQL 是支持编译为 SQL ,但是你也可以自行解析,将 PRQL 转换为为具体的 API 调用或者其他查询语言,从而实现对数据的查询,这个也是没有问题的。

注意: 如果你是基于 PRQL 实现自行解析,然后转换为具体的 API 调用,这种方式可能性能更高。从个人编写 PRQL 的 IDE 插件来看,对比 SQL 的解析,PRQL 的解析更快,这也是 PRQL 也适合 NoSQL 的原因。

总结

目前来说,如果程序非常简单,那么使用 SQL + O/R 框架即可。如果你要为前端(FrontEnd)提供数据访问接口,那么 GraphQL 和 HTTP REST API 是一个不错的选择。 如果你的数据主要集中在查询,那么使用 PRQL 查询、O/R 框架更新可能更合适。另外如果你开发自有的 NoSQL 产品,在接入 SQL 支持前,添加一下 PRQL 的支持,可能也是一个不错的选择。

目前 PRQL 的编辑器支持比较弱一些,不过已经有 VS Code 的插件支持,如果你使用 JetBrains IDE 的话,你可以尝试一下JetBrains PRQL 插件, 语法高亮、代码提示、SQL 自动生成和数据库集成等特性都包含,功能非常不错。

想要了解更多?

欢迎大家关注我们公众号定期推荐有趣的开发者工具,也欢迎大家加入我们微信群一起讨论和交流:

广告: 开发者的万能工具箱 He3 也发布了新版本,欢迎试用: he3.app

1699 次点击
所在节点    程序员
4 条回复
zhlxsh
2023-01-13 10:27:27 +08:00
本人做 sre ,之前看到 GraphQL 也想在项目里用一下, 但是内部项目快速上线为主,出问题也是自己维护,所以拿以前的框架套上跑起来就行了😂
dragondove
2023-01-13 11:34:16 +08:00
@zhlxsh GraphQL 用起来感觉也挺麻烦的,但是可以学习一下他的设计来设计自己的 api ,举例你有一个表(比如叫做用户)关联多个表(比如关联钱包信息表,银行卡信息表),那么你可以这样设计接口
```json
{
"userId": 23,
"returnWallet": true,
"returnCards": false
}
```
这个查询条件就表示用户需要 userId 为 23 的这个人的基本信息+钱包信息,但是不需要银行卡列表信息。
你可以默认设置成所有的查询除了基本信息之外都不返回,用户需要的时候传入 returnXXX: true 就给他返回(我个人更喜欢叫做 withXXX )
如果你的接口是个 RPC 接口,你还可以设计一下字段的设置方式,例如我使用 java ,针对这个入参可以设置几个方法
```java
public UserQuery withWallet() {
returnWallet = true;
return this;
}
public UserQuery userId(Long id) {
userId = id;
return this;
}
// 剩下省略
```
那么 RPC 查询就可以是
```java
UserDetailRes userDetail = userRPC.query(new UserQuery.userId(23).withWallet());
```
使用起来也比较流畅
chenlins
2023-01-14 05:45:57 +08:00
GraphQL 怎么做接口权限啊
superchijinpeng
2023-01-16 14:44:20 +08:00
@chenlins 参考 GitHub

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/908615

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX