You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL4下高性能过滤层级权限表无有效父节点数据的方案

适配MySQL4的高性能权限过滤方案

核心思路

因为业务侧权限层级最多4层,且MySQL 4不支持递归CTE,存储过程递归的性能也很差,直接采用固定层级自关联的方案实现,全流程走索引等值关联,没有额外开销,性能最高,完全匹配老版本MySQL的语法支持范围。

前置准备

首先给权限表建关联用的索引,这步是性能基础,只需要执行一次:

-- 如果id已经是主键,不需要重复建第一个索引,主键默认自带索引
CREATE INDEX idx_perm_id ON permissions(id);
CREATE INDEX idx_perm_parentid ON permissions(parentId);

注意:原SQL框架中用ON p.id = toto.id OR p.id = titi.id OR p.id = tutu.id的写法在MySQL4中性能极差,优化器无法为OR跨表关联命中索引,会触发权限表全表扫描,大数据量下根本跑不动,必须替换。

最终实现SQL

直接替换原SQL的关联逻辑即可,不需要改动你原有SET部分的更新赋值逻辑:

UPDATE aggregat_table at
  -- 先把三个业务表的有效权限ID去重合并,避免OR关联的性能问题
  INNER JOIN (
    SELECT id FROM toto
    UNION
    SELECT id FROM titi
    UNION
    SELECT id FROM tutu
  ) valid_perm
  -- 关联当前权限节点
  INNER JOIN permissions p1 
    ON p1.id = valid_perm.id
  -- 关联1级父节点(直接上级)
  LEFT JOIN permissions p2 
    ON p1.parentId = p2.id
  -- 关联2级父节点(爷爷节点)
  LEFT JOIN permissions p3 
    ON p2.parentId = p3.id
  -- 关联3级父节点(曾祖父节点,覆盖最多4层权限的业务场景)
  LEFT JOIN permissions p4 
    ON p3.parentId = p4.id
  WHERE
    -- 根权限直接保留
    p1.parentId = 0
    -- 2级权限:父节点存在且父节点是根
    OR (p1.parentId <> 0 AND p2.id IS NOT NULL AND p2.parentId = 0)
    -- 3级权限:父、爷节点都存在,爷爷节点是根
    OR (p2.parentId <> 0 AND p3.id IS NOT NULL AND p3.parentId = 0)
    -- 4级权限:父、爷、曾祖节点都存在,曾祖节点是根
    OR (p3.parentId <> 0 AND p4.id IS NOT NULL AND p4.parentId = 0)
  SET -- 此处保留原有更新赋值逻辑即可

逻辑说明

  • 所有关联都是等值匹配,完全命中提前建好的索引,MySQL4优化器可以正常生成高效执行计划,不会出现全表扫描,百万级数据下也能快速跑完
  • 过滤逻辑完全匹配需求:只要权限链路中任意一层父节点缺失,对应LEFT JOIN的结果就会返回NULL,无法满足WHERE条件,会被直接过滤。用给出的示例数据验证:
    • id=5的父节点是4,不存在,p2返回NULL,被过滤
    • id=7的父节点是6,不存在,p2返回NULL,被过滤
    • id=8的父节点是7,7的父节点6不存在,p3返回NULL,被过滤
    • 最终保留的正好是id=1、2、3三个有效权限,和预期结果完全一致

扩展说明

如果后续业务权限层级最多增加到5层,只需要多补一次LEFT JOIN关联p5节点,再在WHERE中增加对应层级的判断分支即可,维护成本极低。

内容的提问来源于stack exchange,提问作者mmeisson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 08:18:33