mysql无限层表设计方案分析

目录

需求接口

思路1:记录父ID

思路2:闭包表(空间换时间)

思路3:存储路径

三种方式对比


本文所用的层级关系图 

需求接口

1、获取子级/所有子级列表/所有子级树

2、获取父级

3、增删改

思路1:记录父ID

CREATE TABLE `XXX` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
  `parent_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '上级ID',
  `is_leaf` tinyint(2) NOT NULL DEFAULT '0' COMMENT '叶子结点标记:0非叶子,1叶子',
  ...
} 

存储结果(根据文章开始的图中ID)

思路2:闭包表(空间换时间)

两个表,每个关系都存起来

create table XXX_base{
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
  `name` varchar() NOT NULL COMMENT '',
  ...
}

create table XXXrelation{
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
  `base_id` bigint(20) unsigned NOT NULL COMMEMT '基础信息表ID',
  `base_parent_id` bigint(20) unsigned NOT NULL COMMEMT '上级的基础信息ID',
  `diff_level` tinyint(2) NOT NULL DEFAULT '0' COMMENT '与父节点相差的层级',
  `is_leaf` tinyint(2) NOT NULL DEFAULT '0' COMMENT '叶子结点标记:0非叶子,1叶子',
  ...
}

存储结果(根据文章开始的图中ID)

思路3:存储路径

存储从第一层到自己的路径

CREATE TABLE `XXX` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
  `parent_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '上级ID',
  `path` varchar(255) NOT NULL DEFAULT '' COMMENT '层级路径',
  `is_leaf` tinyint(2) NOT NULL DEFAULT '0' COMMENT '叶子结点标记:0非叶子,1叶子',
  ...
} 

存储结果(根据文章开始的图中ID)

三种方式对比

三种思路对比记录父ID闭包表存储路径
获取子级

where parent_id = ? O(1)

where base_parent_id = ? and diff_level = 1 O(1)

where parent_id = ? O(1)

获取子级列表

获取子级树

递归向下查询,并且循环访问数据库 O(n)

where base_parent_id = ?

O(1)

where path like 'pathPrefix-%' O(1)

获取父级select parent_id where id = ?O(1)

select base_parent_id where base_id = ? and diff_level = 1

O(1)
select parent_id where id = ?O(1)

是否有层级关系

递归向下查询,并且循环访问数据库 最坏O(n)

where base_id = ? and base_parent_id = ? O(1)

fromPath.get(1).equals(toPath.get(1)) ?O(1)

索引parent_id

base_id;base_parent_id

parent_id;path

查询性能分析比较

获取所有子级递归性能非常低,大量IO

关系表存储数据有重复性,如果一棵树一共有100个节点,那树根需要存储100条数据,影响查询效率

很清晰,查询最优

新增(可绑定父级、子级list)

1、id = insert into

2、入参父级is_leaf为1

3、select * where id in (入参子级list):处理原父级is_leaf && update set parent_id = id

O(1)

1、id = insert into

2、入参父级is_leaf为1

3、delete from where base_id in (入参子级list)

select * where base_id = 入参父级,获取所有父级记录,按照入参父级新增记录

select * from base_parent_id in (入参子级list),处理子级列表:删除、按照父级记录新增

O(1)

1、id = insert into

2、入参父级is_leaf为1

3、select * where id in (入参子级list):处理原父级is_leaf && 处理path、parent_id

循环入参子级list:select * where path like '子节点pathPrefix-%' :批量update path

O(n)

修改(父级更新:原父级 -> 更新父级)

1、处理原父级is_leaf

2、update parent_id = 新父级

O(1)

1、处理原父级is_leaf

2、删除当前节点记录,按照新父级记录新增

3、select * from base_parent_id = 当前节点,获取所有子级,删除、按照当前节点的记录新增

O(1)

1、处理原父级is_leaf

2、select * where path like '当前节点pathPrefix%' :处理path、parent_id

O(1)

删除(只能删除叶子节点)

1、delete from where id = ?

2、处理父级is_leaf:获取子级为空则为is_leaf = 0

O(1)

1、delete from where base_id = ?

2、处理父级is_leaf:获取子级为空则为is_leaf = 0

O(1)

1、delete from where id = ?

2、处理父级is_leaf:获取子级为空则为is_leaf = 0

O(1)

优缺点分析

优:复杂度低,维护性能高

缺:多层查询性能低

优:性能高

缺:复杂度高,存储空间大

优:查询性能最高,复杂度低

缺:新增性能低

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值