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

这里的大尺寸字段指的是 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);
}, []));

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

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

《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!