美文网首页
通过位运算优化数据库设计

通过位运算优化数据库设计

作者: 小一_127b | 来源:发表于2020-08-14 23:21 被阅读0次

场景:

在之前做的考勤系统,有个考勤配置的功能,需要从周一到周天每天设置一个开关来支持每天是否开启考勤。当时实现这个功能觉得 so easy! ,但最近突然想到了一个自己觉得更加简单的实现方式,顺便记录下,下面是两种实现方式。

旧数据库设计

这个是我最初的实现方式,创建了两张表,保存考勤配置信息的考勤配置表,关联考勤配置表保存开关信息的开关表。然后添加周一到周天7条记录,每条记录对应每天是否开启考勤。下面是表结构:

  1. 考勤配置表(cfg_attend)
FEILD TYPE LENGTH PRIMARY NULL REMARK
id char 32 主键ID
tenant_id char 32 租户ID
start_time time 0 上学考勤时间(如9:00)
late_minutes int 11 迟到时间(单位分钟)
end_time time 0 放学考勤时间(如12:00)
early_minutes int 11 早退时间(单位为分钟)
creator_id char 32 创建人ID
create_time datetime 0 创建时间
modify_time datetime 0 更新时间
deleted tinyint 4 删除标记(0-未删除 1-已删除)
  1. 考勤开关表(cfg_week_on)
FEILD TYPE LENGTH PRIMARY NULL REMARK
id char 32 主键ID
ca_id char 32 配置表ID
week_day tinyint 4 周几
on tinyint 4 是否开启考勤(0-未开启 1-开启)
creator_id char 32 创建人ID
create_time datetime 0 创建时间
modify_time datetime 0 更新时间
deleted tinyint 4 删除标记(0-未删除 1-已删除)

在这个设计中,我们需要从数据库查询出考勤配置以及对应的开关表数据,然后根据开关字段判断是否开启考勤。实现代码如下:

  1. 查询出考勤配置表数据
select * from cfg_attend where deleted = 0 and tenant_id = {租户ID}
  1. 获取当天周几
int weekDay = LocalDate.now().getDayOfWeek().getValue(); // 当天为周几
  1. 根据配置表ID和周几去查询出考勤配置对应的开关数据
select * from cfg_week_on where deleted = 0 and ca_id = {配置表ID} and week_day = {周几}
  1. 使用字段 on 判断是否开启了考勤
public static boolean currentAttendIsOn(int on) {
    return on == 1;
}

新数据库设计:

在这个实现方式中去除了考勤开关表,在考勤配置表中添加了有效星期几字段来存储考勤开关。下面是表结构:

  1. 考勤配置表(cfg_attend)
FEILD TYPE LENGTH PRIMARY NULL REMARK
id char 32 主键ID
tenant_id char 32 租户ID
start_time time 0 上学考勤时间(如9:00)
late_minutes int 11 迟到时间(单位分钟)
end_time time 0 放学考勤时间(如12:00)
early_minutes int 11 早退时间(单位为分钟)
week_days char 7 有效星期几,如0011111,表示周六、周日不生效
creator_id char 32 创建人ID
create_time datetime 0 创建时间
modify_time datetime 0 更新时间
deleted tinyint 4 删除标记(0-未删除 1-已删除)

在这个设计中,我们只需要从数据库查询出考勤配置 ,然后根据有效星期几字段进行位运算即可判断出是否开启考勤。实现代码如下:

  1. 查询出考勤配置表数据
select * from cfg_attend where deleted = 0 and tenant_id = {租户ID}
  1. 使用字段 week_days 判断是否开启了考勤
public static boolean currentAttendIsOn(String weekDays) {
    // 传入的字符串从左往右一次代表周一到周天,但是我们计算的时候是需要从右到左
    // String reverseWeekDays = new StringBuilder(weekDays).reverse().toString();
    int weekDay = LocalDate.now().getDayOfWeek().getValue(); // 当天为周几
    int weekDaysValue = Integer.parseInt(weekDays, 2); // 二进制转换位整数
    int currentDayValue = 1 << (weekDay - 1);
    return (weekDaysValue & currentDayValue) == currentDayValue;
}

对比两种实现方式,可以发现:

  1. 第一种实现多一张数据库表,且多一次数据库操作,效率稍低,但是简单易懂;
  2. 第二种实现少一张数据库表,且只需一次数据库操作,效率较高,但需要会位运算;

相关文章

网友评论

      本文标题:通过位运算优化数据库设计

      本文链接:https://www.haomeiwen.com/subject/cetodktx.html