V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
hongchaodeng
V2EX  ›  程序员

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

  •  
  •   hongchaodeng · 2023-01-13 10:03:59 +08:00 · 1656 次点击
    这是一个创建于 440 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

    几点注意事项:

    • 这三者都是基于一个 Endpoint 来实现数据查询和更新的。如 GraphQL 就对应http://localhost:8080/graphql。数据库则为jdbc:postgresql://localhost:5432/postgres。PRQL 可以被翻译为 SQL ,所以接入点跟 SQL 是一样的。
    • PRQL 是基于查询的,并不支持数据的更新。但是不代表功能缺陷,2-8 原则大家都明白的,即便是 SQL ,80%的操作主要是 select 。
    • 只有 GraphQL 是支持订阅的,当然你也可以使用 CDC 工具,将数据库变更发送到 MQ 系统上,然后基于 MQ 订阅,如Debezium

    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

    4 条回复    2023-01-16 14:44:20 +08:00
    zhlxsh
        1
    zhlxsh  
       2023-01-13 10:27:27 +08:00 via iPhone
    本人做 sre ,之前看到 GraphQL 也想在项目里用一下, 但是内部项目快速上线为主,出问题也是自己维护,所以拿以前的框架套上跑起来就行了😂
    dragondove
        2
    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
        3
    chenlins  
       2023-01-14 05:45:57 +08:00 via iPhone
    GraphQL 怎么做接口权限啊
    superchijinpeng
        4
    superchijinpeng  
       2023-01-16 14:44:20 +08:00
    @chenlins 参考 GitHub
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3253 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 12:12 · PVG 20:12 · LAX 05:12 · JFK 08:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.