美文网首页
架构师方案-人事系统的核心-时间轴

架构师方案-人事系统的核心-时间轴

作者: 香沙小熊 | 来源:发表于2023-12-15 12:33 被阅读0次

1. 什么是时间轴

所有发生的事件,都被按照时间的顺序详细记录,可以通过切换时间追溯到历史上任何一天,展示当时的状态。简单地说,就是给每一条数据更新打上一个时间戳,目的是可追溯。

image.png

2. 时间轴的应用

时间轴在人力资源规划模块、招聘与配置模块、培训与发展模块、薪酬管理模块等都有着非常重要的应用。

以薪酬管理模块为例:首先薪酬计算天然就存在时间上的错位,比如我们7月份算的发的是6月份的工资,依据的都是6月份的考勤数据、绩效数据、扣款数据。比如奖金的发放需要依据的是前几个月的数据。年终奖的发放则需要依据全年发生的数据进行计算。

3. 设计时间轴需要考虑的问题

数据量的激增: 好比原来围绕员工有100条数据,升维以后就可能增加几倍到几十倍,这样,保持原有的数据存储和查询性能就需要更加先进的数据处理技术;

对于数据的查询和应用: 特别是涉及到关联性的维护,就需要逐一分辨查询的业务逻辑,是应该使用最新的还是某个具体时间点的数据,需要考虑的业务逻辑自然远远比仅仅记录当前值要复杂;

用户体验: 怎么样能够让用户几乎无感知地自动保存历史、查询引用历史,同时还能在需要时完成必要的交互,保持时间轴数据的完整性和一致性,更加需要精密的设计。

如下图,腾讯使用PeopleSoft(2013年)。除了腾讯,Google、IBM、Yahoo...也在使用SAP或Oracle PeopleSoft的HR系统

image.png

4. 实现方案

4.1 定时快照snapshot模式

比如数据每天凌晨定时备份昨天数据

以人事为例,人事一天会多次调整修改员工数据。但是,我们可能只会用到最后一次数据作为当天数据进行核算。

#员工实时表
CREATE TABLE `t_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键标识',
  `employee_no` varchar(50) COLLATE utf8mb4_bin NOT NULL COMMENT '员工工号',
  `name` varchar(100) COLLATE utf8mb4_bin DEFAULT '' COMMENT '姓名',
  `dept_id` int(11) DEFAULT NULL COMMENT '部门id',
  `job_id` int(11) DEFAULT NULL COMMENT '岗位id',
   #...员工其他信息
  `status`tinyint(2) DEFAULT '0' COMMENT '-1:离职、 0:在职',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uni_employee_no` (`employee_no`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=DYNAMIC COMMENT='员工最新数据表'

凌晨备份当前最新数据

#员工每天备份表
CREATE TABLE `t_user_bk` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键标识',
  `employee_no` varchar(50) COLLATE utf8mb4_bin NOT NULL COMMENT '员工工号',
  `name` varchar(100) COLLATE utf8mb4_bin DEFAULT '' COMMENT '姓名',
  `dept_id` int(11) DEFAULT NULL COMMENT '部门id',
  `job_id` int(11) DEFAULT NULL COMMENT '岗位id',
   #...员工其他信息
  `status` tinyint(2) DEFAULT '0' COMMENT '-1:离职、 0:在职',
  `bk_day_no` int(8) DEFAULT NULL COMMENT '备份时间:以天为单位,时间格式: yyyymmdd',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uni_employee_no_bk_day_no` (`employee_no`,`bk_day_no`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=DYNAMIC COMMENT='员工每天备份表'

4.2.2 使用示例

select * from t_user_bk where bk_day_no>20240101 or bk_day_no<20240112

4.2.3 数据维护方法

  • 每天备份最新数据
  • 异常数据额外清洗

4.2 时间区间模式(SAP使用)

4.2.1 设计原则
  • 每个信息类型记录都有开始时间、结束时间
  • 每个信息类型都受时间特性类型的控制
image.png

时间区间字段

  `start_date` datetime DEFAULT NULL COMMENT '开始日期',
  `end_date` datetime DEFAULT NULL COMMENT '结束日期',
4.2.2 使用示例
CREATE TABLE `t_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键标识',
  `employee_no` varchar(50) COLLATE utf8mb4_bin NOT NULL COMMENT '员工工号',
  `name` varchar(100) COLLATE utf8mb4_bin DEFAULT '' COMMENT '姓名',
  `dept_id` int(11) DEFAULT NULL COMMENT '部门id',
  `start_date` datetime DEFAULT NULL COMMENT '开始日期',
  `end_date` datetime DEFAULT NULL COMMENT '结束日期',
  `status` tinyint(2) DEFAULT '0' COMMENT '-1:离职、 0:在职',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uni_employee_no` (`employee_no`)
) ENGINE=InnoDB AUTO_INCREMENT=130243 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=DYNAMIC COMMENT='员工入职离职记录表'
select * from t_user where start_date < '2022-12-31' and end_date < '2023-03-01';
4.2.3 数据维护方法
  • 添加最新或未来数据时,需将最后一条数据的结束时间改为新数据开始时间,新数据结束时间改为无穷大
  • 插入历史中间数据时,需将有冲突的历史数据开始结束时间做避让,空开新数据的时间区间。如果新数据将历史数据完整包含,历史数据将会被完全覆盖(对于时间特性1类型的数据)

4.3 生效字段模式(Oracle PeopleSoft使用)

4.3.1 设计原则

通过生效日期effect_date、生效状态effect_status、生效序号effect_seq三个简单的字段把系统内的任何一条信息在过去、现在、未来三个截面上构建了连续的数据模型,并且不会影响到数据的使用、展示、和对外提供。

日期类型 描述
当前日期-当前数据 当前日期指的是过去最接近今天(含今天)的日期,具有实时性,与当前日期对应的数据行即为单签数据。当前日期由有且仅有一个,当前数据也有且仅有一行。
历史日期-历史数据 小于当前日期的所有日期都是历史日期,与历史日期对应的数据行即为历史数据。显然历史数据可以有多行。
将来日期-将来数据 大于当前日期的所有日期都是将来日期,与将来日期对应的数据行即为将来数据。显然将来数据可以有多行。
通过生效日期,我们可以按时间线准确地维护数据。这样就可以回溯历史信息,同时可以安排将来的事件。

例如,假设今天是2024年4月25日,人事创建一个在2024年5月1日生效的新部门A。但是将来日期,普通员工看不到此记录。

4.3.3 使用示例
CREATE TABLE `t_department` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键id',
  `dept_code` varchar(30) NOT NULL COMMENT '部门编号',
  `parent_dept_code` varchar(30) NOT NULL DEFAULT '' COMMENT '父部门编号',
  `effect_date` date NOT NULL COMMENT '生效日期',
  `effect_seq` int(11) NOT NULL COMMENT '生效序号',
  `dept_name` varchar(30) NOT NULL COMMENT '部门名称',
  `leader_id` varchar(20) NOT NULL COMMENT '部门负责人工号',
  `status` int(11) NOT NULL COMMENT '部门状态0:失效,1:生效',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=latin1
#查询某个时间所有生效部门
select *
from t_department a
where a.effect_date =
      (select max(b.effect_date) from t_department b where b.dept_code = a.dept_code and b.effect_date <= '2024-12-01')
  and a.effect_seq =
      (select max(c.effect_seq) from t_department c where c.dept_code = a.dept_code and c.effect_date = a.effect_date)
  and a.status = 1;
所有数据
查询结果
4.3.3 数据维护方法
  • 添加或插入数据时,按期望的生效日期插入,如果当天已存在记录,则按序号添加,或在老序号中间插入,未来数据和历史数据同理。

5.方案对比

方案 优点 缺点
定时快照snapshot模式 能快速查看某一天的所有数据 全量数据备份数据冗余过多,处理未来事件比较麻烦,修复数据可能要前后的天数比较多
时间区间模式 sql查询时,只需按所需的日期在开始结束范围内查询,即可确定当时唯一的一组数据 因其对每条数据的开始结束时间都有不可重叠的强校验,因此编辑或者修复任何一条数据,都需要同时修改相邻的数据,这增加系统运维的复杂度
生效字段模式 维护时只需要对应按生效日期添加数据、修改数据、删除数据,可以较方便地对历史回溯数据进行修改。 sql查询时,有effect_date和effect_seq两个维度需要取max,sql语句取值较复杂,且容易出错。

6.参考

事业窗-人力资源数字化的那些黑科技(一):时间轴
得物-人事系统时间轴设计的演化历程
小彭同学-你为什么做不好人力资源系统?(二)——时间轴在HR场景中的应用
Crystal-时间轴是什么?怎么用

相关文章

网友评论

      本文标题:架构师方案-人事系统的核心-时间轴

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