如何优化Laravel9.x深度层级无限级分类查询性能

老明大大_3688

老明大大_3688

2026-10-27

560人浏览

原创

优化Laravel 9.x无限级分类性能的关键是分场景选模型、控查询范围、减数据体积、准缓存管理:≤5层用邻接表+预加载;>5层且读多写少用nestedset;禁用无限with嵌套,改用CTE查ID再批量获取;缓存需带版本号与主动失效机制。

如何优化laravel9.x深度层级无限级分类查询性能

优化 Laravel 9.x 深度层级无限级分类查询性能,关键不是“怎么查得更深”,而是“怎么避免查得慢又不稳”。邻接表(parent_id)模型天然不适合深度遍历,硬扛递归或嵌套 with 容易触发 N+1、内存溢出或 MySQL 堆栈超限。真正有效的策略是分场景选模型、控查询范围、减数据体积、准缓存管理。

优先评估是否真需“无限深度”

多数业务中所谓“无限级”,实际有效深度 rarely 超过 4–6 层(如:类目 → 大类 → 中类 → 小类 → 品牌 → SKU)。若确定不会超过 5 层,用邻接表 + 预加载即可,无需上复杂方案:

  • 定义好 parent_id 允许 null,并加索引:$table->index('parent_id');
  • 查根节点及全部子树(≤3 层):Category::whereNull('parent_id')->with(['children' => fn($q) => $q->with('children')])->get();
  • 查某节点下全部后代(≤4 层):Category::where('id', $id)->with(['children' => fn($q) => $q->with(['children' => fn($q2) => $q2->with('children')])])->first();

深度 > 5 层且读多写少?换 nestedset 扩展包

kalnoy/nestedset 使用左右值(_lft/_rgt)模型,单次查询即可获取整棵子树或路径,适合后台类目管理、前台静态导航等场景:

laravel-specialist
laravel-specialist

精通 Laravel 10+,遵循现代 PHP 实践的 Laravel 专家。擅长优雅语法、Eloquent ORM、队列系统及企业级特性...

下载
  • 安装:composer require kalnoy/nestedset
  • 迁移中调用 NestedSet::columns($table),自动生成 _lft、_rgt、parent_id
  • 查某节点所有后代:$node->descendants;(一条 SELECT,无递归)
  • 查某节点完整路径:$node->ancestors;(同样高效)
  • 注意:插入/移动节点会重算左右值,写操作略重,不适合高频变动的树

拒绝 N+1,也别滥用 with('relation') 无限嵌套

with('children.children.children...') 看似简洁,但 Eloquent 不会自动截断层级,容易生成冗余查询或空集合爆炸。更稳的做法是“两步走”:

  • 第一步:用原生递归 CTE 查出所有相关 ID(MySQL 8.0+ 或 PostgreSQL 支持):
    DB::select("WITH RECURSIVE tree AS (SELECT id, parent_id FROM categories WHERE id = ? UNION ALL SELECT c.id, c.parent_id FROM categories c INNER JOIN tree t ON c.parent_id = t.id) SELECT id FROM tree", [$rootId]);
  • 第二步:用这些 ID 一次查出全部节点:Category::whereIn('id', $allIds)->get();
  • 最后在 PHP 层用 collect()->groupBy('parent_id') 构建树结构——轻量、可控、无深度限制

缓存必须带层级语义和主动失效

分类树缓存一旦污染,整个导航就错乱。不能只缓存一个键,也不能只靠 TTL:

  • 键名含业务维度,例如:"category:tree:root_{$rootId}:v3",版本号 v3 便于全量刷新
  • 对每个节点变更(新增/移动/删除),清除其父节点缓存:Cache::forget("category:tree:root_{$parentId}:v3");
  • 用 Redis tags 分组管理:Cache::tags(['category-tree', "root-{$rootId}"])->remember(...),删时可精准批量清理
  • 根节点缓存 TTL 设为 1 小时,子节点继承;但用户编辑后立即 forget(),不等过期

相关文章

数码产品性能查询
数码产品性能查询

该软件包括了市面上所有手机CPU,手机跑分情况,电脑CPU,电脑产品信息等等,方便需要大家查阅数码产品最新情况,了解产品特性,能够进行对比选择最具性价比的商品。

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

2023.09.01

11544

6

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.11

6681

5

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.11

2175

5

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

2023.10.23

4228

4

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

2023.10.23

4934

6

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.03

3871

9

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.09

5597

8

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.13

4382

8

sprintf函数用法详解
sprintf函数用法详解

sprintf函数的用法:1、格式化字符串;2、指定输出宽度和精度;3、返回值。更多关于sprintf函数用法详解的内容,大家可以阅读下面的文章。

2023.11.27

12302

4

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
如何安装 Composer
如何安装 Composer

共1课时 | 213人学习

Composer手册
Composer手册

共0课时 | 0人学习