近期需要一个汇总统计,由于数据太多,数据量太大所以在java程序中实现比较困难。若用后台程序统计,数据不能保证实时,同时实现周期比较长。顾使用函数返回结果集的方式,在不增加临时表的情况下实时获取数据。需求为:多个端口流量每五分钟累计汇总一次。如果用程序实现则为讲所有数据取出做每五分钟统计,元数据获取带来的数据量将是10万条以上。
在数据库中做汇总统计只需要24*12=288条记录。
具体实现方式如下:
/*打开日志输出*/ Set serveroutput on ; /*创建类型*/ create or replace type type_flux_data_stat_o as object ( ifinoctetsbps number , ifoutoctetsbps number , collecttime number ); /*创建类型归属为表类型*/ create or replace type type_flux_data_stat as table of type_flux_data_stat_o; /*pipelined创建函数 返回表类型*/ create or replace FUNCTION f_linkgroupstat(begin_time IN NUMBER, end_time IN NUMBER, lg_id in varchar2, table_name varchar2 ) return type_flux_data_stat pipelined as /*游标申明*/ v_Cur SYS_REFCURSOR ; /*sql临时变量*/ v_SQLStatement string (10000 ); /*表类型*/ v_Table type_flux_data_stat_o; /*流入字节数临时变量*/ tmp_ifinoctetsbps NUMBER ; /*流出字节数临时变量*/ tmp_ifoutoctetsbps NUMBER ; /*流入字节数汇总*/ total_ifinoctetsbps NUMBER ; /*流出字节数汇总*/ total_ifoutoctetsbps NUMBER ; /*起始时间窗格*/ tmp_begin_time NUMBER ; /*结束时间窗格*/ tmp_end_time NUMBER ; begin /*时间窗格偏移量为5分钟(300秒)*/ tmp_begin_time := begin_time; tmp_end_time := begin_time + 300 ; total_ifinoctetsbps := 0 ; total_ifoutoctetsbps := 0 ; loop exit when tmp_begin_time > end_time; v_SQLStatement := 'select sum(ifinoctetsbps) ifinoctetsbps,sum(ifoutoctetsbps) ifoutoctetsbps from ' || table_name || ' a where exists (select 1 from tm_linkgroup_cportdirection b where a.getway = b.getway and a.port_info=b.ifindex_info and lg_id in (' || lg_id || ') and a.device_id = b.device_id ) and a.collecttime >=' || tmp_begin_time || ' and a.collecttime <=' || tmp_end_time || ' order by collecttime' ; Dbms_Output.put_line(v_SQLStatement); /*针对字符串sql打开游标*/ open v_Cur for v_SQLStatement; tmp_begin_time := tmp_begin_time + 300 ; tmp_end_time := tmp_end_time + 300 ; total_ifinoctetsbps := 0 ; total_ifoutoctetsbps := 0 ; loop /*将游标的值放入零食变量中*/ fetch v_Cur into tmp_ifinoctetsbps, tmp_ifoutoctetsbps; /*当游标中不存在值时跳出游标*/ EXIT WHEN v_Cur% NOTFOUND; total_ifinoctetsbps := total_ifinoctetsbps + tmp_ifinoctetsbps;
total_ifoutoctetsbps := total_ifoutoctetsbps + tmp_ifoutoctetsbps; end loop ; /*单行记录初始化*/ v_Table := type_flux_data_stat_o(total_ifinoctetsbps, total_ifoutoctetsbps, tmp_begin_time); /*将记录压入至结果集中*/ pipe row (v_Table); /*关闭游标*/ close v_Cur; end loop ; Exception when others then Dbms_Output.put_line( Sqlerrm ); end f_linkgroupstat;
使用方法为table(方法)作为表查询方式,其间没有临时表,形如:
select * from table(f_linkgroupstat(1361980800,1362067200,'34','FLUX_DATA_2013_2_28')) a; 289 rows selected. Elapsed: 00:00:00.28
执行时间为:28ms