现状:
表查询次数较多,修改顺序次数较少。
需要向历史数据中增加排序字段来保存用户自定义顺序。
设备表数据量目前是几万,同一个房间内设备数最多为几百。
方案一:中位数法
实现步骤
一、环境准备
新增数据库字段device_order(bigint 65536=2^16),device_order字段中保存排序用数值。
列表查询sql改为 order by device_order desc。
批量修改数据库device_order的值, 根据device_sort和最后修改时间排序,在全表中顺序写入整型的值。
如果不提前设置数据库中字段的默认值,那么就会出现首次进入后无法保存某条数据的具体位置的情况,列表查询的sql也会更加复杂。
批量修改的sql如下:
update device
set device_order = (@pre_value := @pre_value + 65536)
order by device_sort, @pre_value := 65536
二、后台代码逻辑
app端实际拖拽数据后,接口向后台发送「x,y」字段。假设有任务A,B,C计算规则如下:
- 如果C要移到A的前面,前台传入「null,A.id」 ,后端会把 C.device_order 改为 A.device_order>>1;
- 若果C要移到A和B之间,前台传入「A.id,B.id」 , 那么后端会把 C.device_order 改为 (A.device_order + B.device_order)>>1;
- 如果B要移到C的后面,前台传入「C.id,null」 , 那么后端会把 B.device_order 改为 C.device_order + 65536
如果A.device_order和B.device_order中间间隔小于设定好的某个阈值(64?),将项目ID写入redis。
若C的类型为一组的话,将根据A.device_order和B.device_order的值重置这一组的order值。(设置组内最大数量为9,避免性能问题)
三定时任务
1.读取redis,将获取到的项目id下的所有设备列表中的device_order重新初始化为整型的值。
方案二:链表法
增加数据库表字段 device_pre、device_after。使用两个字段保存前一个和后一个数据的id。
适用于频繁修改顺序和不经常查询的情况下。
方案三:二叉树法
不适应频繁的分组查询
原代码逻辑:
删除设备
(无改动)
新增设备
调用设备置顶的方法,将设备设置为首位 device_order=A.device_order/2;