1、背景
现用户存在上级代理、销售,其上级代理、销售也可拥有上级代理、销售。通俗来说就是可能会存在无限多的分支即无限多的祖先-后代关系。
2、问题
现维护代理、销售链的方式是通过api_users表中的agent、sales字段来进行维护,可理解为父ID。若要查询其所有父级节点、子级节点或者整条链路时,需要通过父ID递归进行查询,随着层级的增多,递归次数也会增多,会造成较多的IO操作,使得效率变慢。
3、方案
示例数据:
3.1、邻接表(现有模式)
记录父id,即现在数据库的agent、sales字段
id | name | pid |
---|---|---|
01 | 一级代理 | |
0101 | 二级代理 | 01 |
0102 | 二级代理 | 01 |
010101 | 三级代理 | 0101 |
010102 | 三级代理 | 0101 |
010103 | 三级代理 | 0101 |
010201 | 三级代理 | 0102 |
01010101 | 四级代理 | 010101 |
查询父节点:通过pid查询对应的父节点
查询所有父节点:通过递归查询所有的父节点
查询子节点:通过id查询对应的子节点
查询所有子节点:通过递归查询所有的父节点
查询整条链路:通过递归查询整条链路
删除某个节点:删除该条数据,并通过id把子节点的pid置空
修改某个节点的父节点:修改该条数据的pid
新增节点:维护pid即可
3.2、全路径存储
增加全路径(path)字段,记录顶级节点到自己本身的路径,用“,”英文逗号隔开
id | name | pid | path |
---|---|---|---|
01 | 一级代理 | 01 | |
0101 | 二级代理 | 01 | 01,0101 |
0102 | 二级代理 | 01 | 01,0102 |
010101 | 三级代理 | 0101 | 01,0101,010101 |
010102 | 三级代理 | 0101 | 01,0101,010102 |
010103 | 三级代理 | 0101 | 01,0101,010103 |
010201 | 三级代理 | 0102 | 01,0102,010201 |
01010101 | 四级代理 | 010101 | 01,0101,010101,01010101 |
查询父节点:通过pid查询对应的父节点
查询所有父节点:通过path字段即可得知所有父节点id,进行查询(1、拆分path字段内容,进行in查询;2、WHERE ‘需查询的全路径’ LIKE path||‘%’)
查询子节点:通过id查询对应的子节点
查询所有子节点:通过模糊查询path字段即可得到所有子节点(1、WHERE path LIKE ‘需查询的全路径%’,2、WHERE find_in_set('需查询的全路径‘, path))
查询整条链路:通过id字段模糊查询path
删除某个节点:需置空其下级节点数据,以及所有子节点都需执行update操作
修改某个节点的父节点:需针对其所有子节点进行update操作,修改path字段
新增节点:复制父节点的path,并添加自身id
需注意的点:理论上来说链路长度为无限,path字段设置长度需谨慎
3.3、闭包表
即除现有表外,增加一个表来维护上下级关系
id | name | pid |
---|---|---|
01 | 一级代理 | |
0101 | 二级代理 | 01 |
0102 | 二级代理 | 01 |
010101 | 三级代理 | 0101 |
010102 | 三级代理 | 0101 |
010103 | 三级代理 | 0101 |
010201 | 三级代理 | 0102 |
01010101 | 四级代理 | 010101 |
关联表
id | base_id | base_parent_id | level |
---|---|---|---|
1 | 01 | 01 | 1 |
2 | 0101 | 0101 | 1 |
3 | 0102 | 0102 | 1 |
4 | 0101 | 01 | 2 |
5 | 0102 | 01 | 2 |
6 | 010101 | 010101 | 1 |
7 | 010102 | 010102 | 1 |
8 | 010103 | 010103 | 1 |
9 | 010101 | 01 | 3 |
10 | 010101 | 0101 | 2 |
11 | 010102 | 01 | 3 |
12 | 010102 | 0101 | 2 |
13 | 010103 | 01 | 3 |
14 | 010103 | 0101 | 2 |
15 | 010201 | 010201 | 1 |
16 | 010201 | 01 | 3 |
17 | 010201 | 0102 | 2 |
18 | 01010101 | 01010101 | 1 |
19 | 01010101 | 01 | 4 |
20 | 01010101 | 0101 | 3 |
21 | 01010101 | 010101 | 2 |
查询父节点:通过pid查询对应的父节点
查询所有父节点:通过base_id字段查询关联表即可
查询子节点:通过id查询对应的子节点
查询所有子节点:通过base_parent_id字段查询关联表即可
查询整条链路:通过base_id与base_parent_id字段查询
修改某个节点的父节点:通过base_id进行查询,得出base_parent_id集合,先删除所有子节点关联关系,再删除对应的所有父节点关系
修改父节点:先删除所有关联关系,再查询需挂靠的节点的所有关联关系,进行复制新增
新增节点:复制父节点所有关联关系,增加自身指向
4、方案分析
邻接表(现有模式)
优:复杂度低,维护性能高
缺:多层查询性能低
全路径存储
优:查询性能最高,复杂度低
缺:新增、修改性能低,字段长度问题无法避免
闭包表
优:性能高
缺:复杂度高,存储空间大