使用 SQL, GraphQL 和 PRQL 进行数据查询 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
hongchaodeng
V2EX    程序员

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

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

    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     Solana     1033 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 23:18 PVG 07:18 LAX 16:18 JFK 19:18
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86