CowNew开源团队网站 http://www.cownew.com
论坛 http://www.cownew.com/newpeng/
转载请注明此版权信息
我准备给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
当然不同的数据库的计算日期时间差和截取整数的方式是略有差异的,我这里用的是mssqlserver的语法。