我准备给JDBMonitor增加一个性能监测报表的功能。用户在“报表条件”中填写要统计的起始时间、结束时间和单位时间后,点击查询。程序从DataBaseDBListener记录的表T_LOG_SQLLog中进行统计并显示报表。例如:用户在起始时间中输入”2006-5-30 18:00:00”,结束时间输入”2006-6-1 12:00:00”,时间单位选择“5分钟”,点击“查询”。程序将把T_LOG_SQLLog中FbeginTime大于等于”2006-5-30 18:00:00”,小于等于”2006-6-1 12:00:00”的记录过滤出来。然后统计每5分钟记录的条数(也就是数据库执行的次数),以时间序列图的形式显示成报表。 比如: fid ftime 1 2006-05-05 10:00:00.000 2 2006-05-05 10:00:01.000 3 2006-05-05 10:00:10.000 4 2006-05-05 10:01:10.000 5 2006-05-05 10:01:20.000
这样的数据属于离散的数据,因为数据库的执行时间是不确定的,要把它们按统计它们的出现次数常常需要使用数据挖掘的东西。数据挖掘通常都是不同的数据库有不同的实现的,JDBMonitor是跨数据库的,因此肯定不能使用这些数据库特有的东西。现在也有一些开源的跨数据库的数据挖掘引擎,但是其尺寸巨大无比,都要50M以上。JDBMonitor是一个小的工具,为了方便部署和使用,JDBMontior的一个基本原则就是尽量避免使用JDK之外的类,所以肯定不能使用它们。我经过仔细思考,发现可以通过如下技巧来解决:
select count(sub.f) as exeCount,min(sub.FBeginTime) as FTime from( select cast(DateDiff(ss,?,FBeginTime)/? as int) as f,FBeginTime from T_LOG_SQLLog )as sub where 1=1 and FBeginTime>=? and FBeginTime<=? group by sub.f order by sub.f ASC
其中第一、三个参数传递用户选择的时间段的起始时间,第二个参数是用户选择的计时间隔(以秒为单位),参数四是用户选择的时间段的结束时间。 我采用的是整除的技巧来实现的这个效果。 其中FBeginTime是SQL语句执行的开始时间(在这里我们就把它看作SQL语句的执行时间),cast(DateDiff(ss,?,FBeginTime)/? as int) as f的意思就是计算SQL语句的执行时间到选择的时间段的起始时间之间的秒间隔数,然后再整除用户选择的计时间隔(以秒为单位)。经过整除以后同一个时间段内的数据就相同了,然后我们一个groupby,然后一个count(sub.f),这样各个时间段sql的执行次数就出来了。 以上边的数据为例,假如我输入的起始时间是2006-05-05 10:00:00.000,结束时间是2006-05-05 10:02:00.000。 那么select cast(DateDiff(ss,?,FBeginTime)/? as int) as f,FBeginTime from T_LOG_SQLLog的结果集就是: f FBeginTime 0 2006-05-05 10:00:00.000 0 2006-05-05 10:00:01.000 0 2006-05-05 10:00:10.000 1 2006-05-05 10:01:00.000 1 2006-05-05 10:01:00.000 然后,以f为分组条件进行汇总,并统计f的count,这样各个时间段sql的执行次数就出来了: 3 2006-05-05 10:00:00.000 2 2006-05-05 10:01:00.000
|