ESAP达摩院 思想有多远,我们就能走多远

ESAP第三弹 清理工作流


概述

ES 工作流的使用在带来诸多便利的同时,也在严重地耗费着资源。 本文将针对数据库中的工作流部分进行分析演示,展示一种扫描清理方案。

分析演示

  • 下图是一个 700 表的数据库的“大头”部分占用情况(前 60%),

  • 其中黄色标记为与工作流相关的数据表,汇总统计情况如下:
–分类– –占比– –区域占比–
紫色 61.09%  
工作流 30.40% 49.77%
系统 27.83% 45.55%
  • 从统计结果来看,工作流约占总空间的 1/3,在大头部分约占 50%!

  • 在正式研究清理方案前,我们需要先认识几个 ES 系统表:

  • ES_RepCase:表单记录,表单的系统信息,如填报人,填报时间等。
  • ES_WfCase:工作流执行,工作流的执行入口。
  • ES_Witodo:工作流待办,工作流的待办人。
  • ES_WiLink:工作流衔接,节点衔接表。
  • ES_WorkItem:工作流汇总,所有的工作流的状态,相关人等。(核心记录)

  • 认识系统表后定出清理方案:指定一个时间点,扫描清理该点之前已完成的所有工作流。

  • 首先,我们从核心记录中选出符合条件的数据。
SELECT  wiid, --节点 ID    
	rcid, --表单 ID    
	piid --工作流 ID 
INTO  #ScanWi  FROM  ES_workitem 
WHERE   datediff(mm,credate,getdate())>= 6 AND state =2   --扫描工作流

上述查询生成一个 3 列的临时表#ScanWi:

  • 其次,以临时表#ScanWi 为参照删除相关工作流信息。
DELETE  FROM ES_WITODO WHERE WIID IN (SELECT WIID FROM #ScanWi)   --删待办 
DELETE  FROM ES_WIlink WHERE WIID IN (SELECT WIID FROM #ScanWi) or PREVWIID IN (SELECT WIID FROM #ScanWi)   --删节点 
DELETE  FROM ES_Wfcase WHERE PIID IN (SELECT PIID FROM #ScanWi)   --删流程 
UPDATE ES_REPCASE SET WIID='' WHERE RCID IN (SELECT RCID FROM #ScanWi)   --恢复表单为普通 

执行效果如下:

  • 再次,是最麻烦的部分,删除工作流快照,由于快照分布在各个数据表的附属 Wi 表中,我们需要从系统表 sysobjects 查出有哪些 Wi 表,然后遍历这些 Wi 表并删除相关数据,这将清理出一大堆空间,哇喔^_^!
IF object_id('tempdb..#ScanTmp') IS NOT NULL    
	DROP TABLE #ScanTmp 
GO 
CREATE TABLE #ScanTmp ( NAME varchar(100),rowid int identity(1,1)) --存放 WI 表名称 
INSERT INTO #ScanTmp  
	SELECT NAME FROM SYSOBJECTS WHERE RIGHT(NAME,3)='_Wi' 
GO 
DECLARE @TmpNo int --wi 模板序号 
DECLARE @MaxNo int --wi 模板数 
DECLARE @TmpName varchar(100)  --wi 模板名称 
SET @MaxNo=@@ROWCOUNT 
SET @TmpNo=1  
WHILE (@TmpNo<=@MaxNo)      --遍历 wi 快照 
BEGIN 
SET @TmpName=(SELECT NAME FROM #ScanTmp WHERE rowid=@TmpNo) --构造执行删除语句 
EXEC ('DELETE FROM  '+ @TmpName + '  WHERE EXCELSERVERWIID IN (SELECT WIID FROM #ScanWi)' ) 
SET @TmpNo=@TmpNo+1 
END 

运行效果如下:(示例中涉及 58 个 wi 表)

  • 接下来,回过头来把 ES_WorkItem 中的记录干掉并删除临时表
DELETE  FROM ES_WorkItem WHERE WIID IN (SELECT WIID FROM #ScanWi)   --删工作流记录 
DROP TABLE #ScanWi    --删除临时表 
DROP TABLE #ScanTmp --删除临时表 

运行效果如下:

  • Ok,大功告成,此时我们再来分析一下数据表占用比例。

可以看出,工作流数据的占用量大幅减少。将半年前的数据清除,使总体占比降到 10%,未清除时为 30%。

细心的读者会发现 ES_WorkItem 表之前有 6W 行记录,清理后为 2W 行,比例为 1:3,与总变化比例吻合,这也印证了清理方案的周全性。

  • 登陆工作台,查看表单记录情况。 临界时间点(半年前)之后的记录进度正常。

临界时间点(半年前)之前的记录已转化为普通表单,不再有进度选项。

应用拓展

  • 将整个过程封装为存储过程,执行 EXEC p_ClearWi 6 就可以删除 6 个月前的工作流了。
CREATE PROC p_ClearWi 
@SMonth INT 
AS 
BEGIN 
DECLARE @TmpNo int 
DECLARE @MaxNo int 
DECLARE @TmpName varchar(100) 
IF object_id('tempdb..#ScanWi') IS NOT NULL    
DROP TABLE #ScanWi --扫描工作流放入临时表,state=2 表示已完成 
SELECT  wiid, --节点 ID   
	rcid, --表单 ID   
	piid --工作流 ID 
INTO  #ScanWi  
FROM  ES_workitem 
WHERE   datediff(mm,credate,getdate())>= @SMonth AND state =2     
DELETE  
FROM ES_WITODO WHERE WIID IN (SELECT WIID FROM #ScanWi)   --删待办  
DELETE  
FROM ES_WIlink WHERE WIID IN (SELECT WIID FROM #ScanWi) OR PREVWIID IN (SELECT WIID FROM #ScanWi)   --删节点  
DELETE  FROM ES_Wfcase WHERE PIID IN (SELECT PIID FROM #ScanWi)   --删流程  
UPDATE ES_REPCASE SET WIID='' WHERE RCID IN (SELECT RCID FROM #ScanWi)   --恢复表单为普通  
IF object_id('tempdb..#ScanTmp') IS NOT NULL    
	DROP TABLE #ScanTmp 
CREATE TABLE #ScanTmp ( NAME varchar(100),rowid int identity(1,1)) --存放 WI 表名称  
INSERT INTO #ScanTmp  
	SELECT NAME FROM SYSOBJECTS WHERE RIGHT(NAME,3)='_Wi'  
SET @MaxNo=@@ROWCOUNT 
SET @TmpNo=1 
WHILE (@TmpNo<=@MaxNo)      --遍历 wi 快照,构造删除语句并执行 
BEGIN 
SET @TmpName=(SELECT NAME FROM #ScanTmp WHERE rowid=@TmpNo) 
EXEC ('DELETE FROM  '+ @TmpName + '  WHERE EXCELSERVERWIID IN (SELECT WIID FROM #ScanWi)' )  
SET @TmpNo=@TmpNo+1 
END  
DELETE  
FROM ES_WorkItem WHERE WIID IN (SELECT WIID FROM #ScanWi)   --删流程  
DROP TABLE #ScanWi    --删除临时表
DROP TABLE #ScanTmp  --删除临时表  
END 
GO 

小结

本文的工作流清理技术与工作流扫描恢复技术,解决了 ES 系统中关于工作流应用的两大顽疾,也使企业在使用工作流时不用再畏手畏脚。本文的示例系统为 9.4,其他版本请自行测试。

注:本文技术仅供借鉴,使用本技术需要一定的数据库知识,尝试本技术所导致的任何后果与本文作者无关。


近似文章