Laravel Eloquent如何过滤JSON字段中存储的date_start属性值
方案合理性评估
你当前的全量查询后本地解码筛选的思路仅适合百条级以内的极小数据量场景,整体属于不合理的实现方案,存在的核心问题包括:
- 全表查询会产生极高的数据库IO、内存开销以及网络传输成本,数据量突破千级后接口性能会出现断崖式下跌,万级以上数据大概率直接触发超时
- 服务端循环解码JSON、逐一匹配的逻辑会额外占用服务端CPU、内存资源,并发量稍高就会导致服务实例负载过高不可用
- 完全无法利用数据库的索引优化能力,属于暴力检索,后续业务增长没有扩展空间
优化实现方案
根据你使用的数据库类型、业务场景可以选择不同的优化方案:
方案1:数据库原生JSON查询(优先推荐)
只要你使用的是主流的新版本数据库(MySQL 5.7+、PostgreSQL、MongoDB等),都支持直接对JSON字段的子属性做查询,高频查询场景还可以通过函数索引/虚拟列索引优化到和普通字段查询一致的性能。
以MySQL为例,查询语法如下:
-- 基础JSON查询写法 SELECT * FROM 你的表名 WHERE meta->>'$.date_start' = '你要匹配的日期值'; -- 范围查询同理,比如查询9月的记录 SELECT * FROM 你的表名 WHERE meta->>'$.date_start' BETWEEN '2021-09-01' AND '2021-09-30';
如果这个查询的使用频率很高,可以新增虚拟列并创建索引彻底解决性能问题:
-- 新增虚拟列,值自动和meta里的date_start绑定 ALTER TABLE 你的表名 ADD COLUMN date_start DATE GENERATED ALWAYS AS (meta->>'$.date_start') VIRTUAL; -- 给虚拟列建索引 CREATE INDEX idx_table_date_start ON 你的表名(date_start);
建完索引之后直接查询date_start字段即可,性能和普通的日期字段查询没有差异。
方案2:字段冗余适配老旧数据库
如果你的数据库版本不支持JSON操作,业务也没有引入其他检索组件的计划,可以直接在表中新增普通date_start字段,写入数据的时候同步把JSON中的日期值写入该字段,后续搜索直接查这个普通字段即可,实现成本极低,性能也是最优的。
方案3:搜索引擎适配多动态属性查询
如果你的业务中有大量类似的JSON动态属性检索需求,可以考虑将需要检索的属性同步到Elasticsearch等搜索引擎中,由搜索引擎承担检索逻辑,数据库仅做原始数据存储,适合复杂检索场景。
内容的提问来源于stack exchange,提问作者sabunan
相关产品推荐
相关产品推荐

