概述
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,其他版本请自行测试。
注:本文技术仅供借鉴,使用本技术需要一定的数据库知识,尝试本技术所导致的任何后果与本文作者无关。