模型中的大尺寸字段该在什么时候获取?

这里的大尺寸字段指的是 TEXT 或 BLOB 或更大内容尺寸的字段

起因#

我最近在写 Laravel 框架的 GraphQL 插件,目前在测试用例中简单实现了通过 graphql-php 和 dataloader-php 两个项目来查询数据的逻辑(实现方式非常简单粗暴,自己都看不下去)。但在数据的字段选择方面遇到了问题:在使用 DataLoader 来获取数据时,是否应该在一开始就全读出来( lighthouse 项目就是这样做的)?

介绍一下 DataLoader 项目#

DataLoader 的一个特点就是会缓冲数据到内存中,这点非常适合 GraphQL 这种查询协议,因为在接口路由入口上无法得知当前查询结果是否会被复用。好比客户端的一次查询中,请求一个订单列表,订单列表用户属性结果可能会重复, DataLoader 针对此种情况进行优化:将此过程抽象成通过一组 key 获取结果的过程,且通过 promise 结构延后执行,可大幅降低 GraphQL 中的重复查询问题和 N + 1 问题。

问题分析#

但 GraphQL 查询的字段是随请求变化的,如果严格按照每次请求的字段进行数据加载,那么一次查询的两个请求中,字段稍微改动一下,将造成结果无法复用。如果采用 lighthouse 项目那种固定加载全部字段的做法也会产生大量开销,严重的情况如果遇到大尺寸字段将可能导致内存超出限制错误。

我的尝试#

我目前采用的方法是:在试用 DataLoader 得时候将当时的查询字段同查询的 key 一起提交给 DataLoader 实例,并在进行数据加载逻辑之前,对字段进行去重合并:

$fields     = array_keys(collect($keys)->pluck(1)->reduce(function ($a, $b) {
    return array_merge($a, $b);
}, []));

这样只能从某种程度上解决问题,虽然规避了将所有字段查出的问题,也尽量解决了不同字段查询的数据复用问题,但如果少量查询中存在大尺寸字段,依然有可能一次性将所有数据的这类字段加载出来,消耗不必要的内存分配开销。

大家遇到这种情况都是怎么处理的?还请不吝赐教。

《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。