这是一个常见的能够衡量一台机器的繁忙程度的报表。
看似简单,也就是一张报表当中放置了多个图表。但实际上由于数据库的单表数据量近亿,直接取数据几乎是不可能的。
并且由于数据库表并不算科学,也就是要要做这个表,需要从四张不同的数据库表当中取数据。我埋头查了好久,才算把这个SQL搞定,贡献出来给大家分享一下。
Select
A.HOST as HOST,
B.PARAMETER.NAME as PARAMETER,
TO_DATE('1970-01-01','yyyy-mm-dd') + trunc(C.TIMESTAMP/(1000*60*60*24)) as DATES,
SUBSTR(TO_CHAR(TO_DATE('1970-01-01','yyyy-mm-dd hh24:mi:ss') + C.TIMESTAMP/(1000*60*60*24),'yyyy-mm-dd hh24:mi:ss'),12,2) as HOURS,
TO_NUMBER(C.VALUE) as VALUE
from
(select * from A where HOST='[?HOST|SERVER6?]') A inner join D D on A.GUID = D.HOST
Inner join (select * from B where B.PARAMETERNAME='CPU'
OR B.PARAMETERNAME='MEMORY'
OR B.PARAMETERNAME='DSKBUSY'
OR B.PARAMETERNAME='IO'
OR B.PARAMETERNAME='FSPERCENT'
OR B.PARAMETERNAME='FSSpace')) B on D.GUID = B.APPLICATION inner join C C on B.GUID = C.AGENT
where TO_DATE('1970-01-01','yyyy-mm-dd') + trunc(C.TIMESTAMP/(1000*60*60*24))>=TO_DATE('[?start|2008-04-05?]','yyyy-mm-dd')
and TO_DATE('1970-01-01','yyyy-mm-dd') + trunc(C.TIMESTAMP/(1000*60*60*24))<=TO_DATE('[?end|2008-04-12?]','yyyy-mm-dd')
在这个SQL里面,首先数据是存在oracle数据库里面的,我面对的第一个问题,就是数据库当中存储的时间都是时间戳,也就是距离1970年1月1号零点的毫秒数。需要将其转化为我们常用的yyyy-MM-dd格式。我一点感觉就是应该用to_date函数。但是只有一个to_date似乎是不能完成彻底的转化。
怎么办呢,google,baidu了无数,都没有找到答案,谁让我不懂什么SQL呢,书到用时方恨少!
一定要把我使用的查询关键词写出来,方便以后哪个兄弟用同样的关键词,至少能搜到我这个答案啊。“毫秒转化为时间”。当然大家肯定也看到了,我转化的方法就是TO_DATE('1970-01-01','yyyy-mm-dd') + trunc(C.TIMESTAMP/(1000*60*60*24))和TO_CHAR(TO_DATE('1970-01-01','yyyy-mm-dd hh24:mi:ss') + C.TIMESTAMP/(1000*60*60*24),'yyyy-mm-dd hh24:mi:ss'),12,2),这两者的区别就是,前者只取年月日,后者则将小时分秒都取出来。
日期型的问题解决了,然后又有一个严重的问题冒出来了,数据量太大,在PL/SQL里面执行,都需要花超过一小时的时间,这个肯定是不能让人接受的。我只好又埋头钻研SQL优化,当当当当,成功的把执行时间降低到了0.47秒!
主要的优化方法,就是把where条件,大部分放到inner join那里去做。说起来其实挺简单,是吧。
然后说说报表吧,这个报表是在一张表当中体现了四个图表,一个日趋势,其它三个都是周趋势。其中第一个图和第二图的统计的指标是一样的,分别都是CPU利用率,内存利用率和磁盘的利用率。这三个指标的组合往往能够代表一台机器的繁忙程度。
然后还有一个图是磁盘的忙率比率,以及文件系统的平均可用空间。
设计的方法就没有什么难度好说了,因为我用的FineReport,做这个报表就是小菜一碟了。直接把刚刚定义好的列拖过来,一个小时,一个日期,两个时间字段分别放到B3C3格子里面。左边A4到A8手工写上指标名字或者将库里面的指标名字拖来,中间拖数据过来。就OK。 然后直接插入图表,选择好数据区域就可以了。Just like excel~
当然,这个表要体现的图表,当然可以不用拖拽数据到报表里面,直接写SQL做图表了。不过,我比较懒,不想写4次SQL,所以,就先把数据拖过来,获得图表要体现的数据,再直接从格子里面读了。所以最后最后,我不想在报表里面看到数据,只要图表,隐藏数据区域就好了。就这么简单。
最后一点,在前面的SQL里面我想大家都看到了,这个报表是有参数的。对这太平常不过了,好像每一张报表都会有时间参数的,没有人说,我不管时间,只统计所有的结果吧。以前用别的工具的时候,有参数的报表,都需要通过自己手写一些JSP或者什么其他的,在页面里面把参数查询的框子弄出来。
但是我不得不重申一次,我比较懒,不喜欢什么都要自己写(当然写上面那个SQL,我也嫌麻烦,但是没办法啊,谁让数据量大呢,连Oracle自己查询都会out of memory)。如果参数可以通过拖拖拽拽,访问报表时候就自动会有这么一个参数页面,该多好。
听说汽车的发明是因为人懒得走路,那么我这种懒人,会不会促进软件越来越人性化呢?答案当然是。所以,就是说,我用的FineReport,是可以这样的。报表里面有什么参数,我只需要把它定位一个位置,访问报表的时候,就可以直接弹出或者有个内嵌的参数查询框子了。溜个图:
具体怎么做,就不多说了,他们家软件的帮助文档写的挺详细的。有兴趣的可以到他们网站down一个看看。地址:www.finereport.com