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

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

作者: 香沙小熊 | 来源:发表于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