首先说明一下背景,最近在用一个客户买的报表工具,这个工具要想显示数据,只能用一个SQL 来处理
相信做个报表的同仁们都知道,那些SQL 有多复杂了,有时候要经过程序复杂的处理才能在得到我们想
要展示的数据,就更别提用一个SQL 来满足要求了,要是碰到很烂的数据库设计,那估计要跳楼了
声明一下,不是我懒,不想在程序里处理,主要是这个报表工具最终生成的是 flash 报表,样式是
蛮漂亮的,他可以说是一个单独的系统,只接受SQL 语句,最后生成一个URL给我们
废话不多说了,先看看SQL ,统计每个整点的一个数量,你可以当成是点击量什么的select e.sect,nvl(a.grp_num,0) as a_num,nvl(b.grp_num,0) as b_num,nvl(c.grp_num,0) as c_num, nvl(d.grp_num,0) as d_num from
(select to_char(accesstime,'HH24') hourpoint,count(systemname) grp_num from t_portal_todo_info where systemname = 'cms' AND TO_CHAR (accesstime, 'yyyy-MM-dd') = '$searchDate$' group by to_char(accesstime,'HH24')) a,
(select to_char(accesstime,'HH24') hourpoint,count(systemname) grp_num from t_portal_todo_info where systemname = 'eds' AND TO_CHAR (accesstime, 'yyyy-MM-dd') = '$searchDate$' group by to_char(accesstime,'HH24')) b,
(select to_char(accesstime,'HH24') hourpoint,count(systemname) grp_num from t_portal_todo_info where systemname = 'eer' AND TO_CHAR (accesstime, 'yyyy-MM-dd') = '$searchDate$' group by to_char(accesstime,'HH24')) c,
(select to_char(accesstime,'HH24') hourpoint,count(systemname) grp_num from t_portal_todo_info where systemname = 'cxpt' AND TO_CHAR (accesstime, 'yyyy-MM-dd') = '$searchDate$' group by to_char(accesstime,'HH24')) d,
(select id,sect from T_PORTAL_TODO_H_SECT) e
where a.hourpoint(+) = e.sect
and b.hourpoint(+) = e.sect
and c.hourpoint(+) = e.sect
and d.hourpoint(+) = e.sect
order by e.id
accesstime 为DATE型字段,精确到时分秒
下面是我的执行计划,不过我看不懂,不知如何优化,只好请教各位高手了帮忙分析下来Plan
SELECT STATEMENT CHOOSECost: 138 Bytes: 7 K Cardinality: 82
18 SORT ORDER BY Cost: 138 Bytes: 7 K Cardinality: 82
17 HASH JOIN OUTER Cost: 112 Bytes: 7 K Cardinality: 82
13 HASH JOIN OUTER Cost: 85 Bytes: 5 K Cardinality: 82
9 HASH JOIN OUTER Cost: 57 Bytes: 4 K Cardinality: 82
5 HASH JOIN OUTER Cost: 30 Bytes: 3 K Cardinality: 82
1 TABLE ACCESS FULL MONITOR.T_PORTAL_TODO_H_SECT Cost: 2 Bytes: 2 K Cardinality: 82
4 VIEW MONITOR. Cost: 27 Bytes: 16 Cardinality: 1
3 SORT GROUP BY Cost: 27 Bytes: 13 Cardinality: 1
2 TABLE ACCESS FULL MONITOR.T_PORTAL_TODO_INFO Cost: 2 Bytes: 13 Cardinality: 1
8 VIEW MONITOR. Cost: 27 Bytes: 16 Cardinality: 1
7 SORT GROUP BY Cost: 27 Bytes: 13 Cardinality: 1
6 TABLE ACCESS FULL MONITOR.T_PORTAL_TODO_INFO Cost: 2 Bytes: 13 Cardinality: 1
12 VIEW MONITOR. Cost: 27 Bytes: 16 Cardinality: 1
11 SORT GROUP BY Cost: 27 Bytes: 13 Cardinality: 1
10 TABLE ACCESS FULL MONITOR.T_PORTAL_TODO_INFO Cost: 2 Bytes: 13 Cardinality: 1
16 VIEW MONITOR. Cost: 27 Bytes: 16 Cardinality: 1
15 SORT GROUP BY Cost: 27 Bytes: 13 Cardinality: 1
14 TABLE ACCESS FULL MONITOR.T_PORTAL_TODO_INFO Cost: 2 Bytes: 13 Cardinality: 1
t_portal_todo_info 表其实有很多的系统类型,字段为systemname
现在想要的效果是用一个多系列柱状图同时显示4个系统的一个访问量,我上面的sql写了4个,
可以理解为默认的,其他的可以在页面上更具用户的选择来动态的现实,也就是说我的 accesstime,systemname两个参数
是从页面传递的,当然每次选择的数量只能是4个,不能多页不能少,时间相同
相信做个报表的同仁们都知道,那些SQL 有多复杂了,有时候要经过程序复杂的处理才能在得到我们想
要展示的数据,就更别提用一个SQL 来满足要求了,要是碰到很烂的数据库设计,那估计要跳楼了
声明一下,不是我懒,不想在程序里处理,主要是这个报表工具最终生成的是 flash 报表,样式是
蛮漂亮的,他可以说是一个单独的系统,只接受SQL 语句,最后生成一个URL给我们
废话不多说了,先看看SQL ,统计每个整点的一个数量,你可以当成是点击量什么的select e.sect,nvl(a.grp_num,0) as a_num,nvl(b.grp_num,0) as b_num,nvl(c.grp_num,0) as c_num, nvl(d.grp_num,0) as d_num from
(select to_char(accesstime,'HH24') hourpoint,count(systemname) grp_num from t_portal_todo_info where systemname = 'cms' AND TO_CHAR (accesstime, 'yyyy-MM-dd') = '$searchDate$' group by to_char(accesstime,'HH24')) a,
(select to_char(accesstime,'HH24') hourpoint,count(systemname) grp_num from t_portal_todo_info where systemname = 'eds' AND TO_CHAR (accesstime, 'yyyy-MM-dd') = '$searchDate$' group by to_char(accesstime,'HH24')) b,
(select to_char(accesstime,'HH24') hourpoint,count(systemname) grp_num from t_portal_todo_info where systemname = 'eer' AND TO_CHAR (accesstime, 'yyyy-MM-dd') = '$searchDate$' group by to_char(accesstime,'HH24')) c,
(select to_char(accesstime,'HH24') hourpoint,count(systemname) grp_num from t_portal_todo_info where systemname = 'cxpt' AND TO_CHAR (accesstime, 'yyyy-MM-dd') = '$searchDate$' group by to_char(accesstime,'HH24')) d,
(select id,sect from T_PORTAL_TODO_H_SECT) e
where a.hourpoint(+) = e.sect
and b.hourpoint(+) = e.sect
and c.hourpoint(+) = e.sect
and d.hourpoint(+) = e.sect
order by e.id
accesstime 为DATE型字段,精确到时分秒
下面是我的执行计划,不过我看不懂,不知如何优化,只好请教各位高手了帮忙分析下来Plan
SELECT STATEMENT CHOOSECost: 138 Bytes: 7 K Cardinality: 82
18 SORT ORDER BY Cost: 138 Bytes: 7 K Cardinality: 82
17 HASH JOIN OUTER Cost: 112 Bytes: 7 K Cardinality: 82
13 HASH JOIN OUTER Cost: 85 Bytes: 5 K Cardinality: 82
9 HASH JOIN OUTER Cost: 57 Bytes: 4 K Cardinality: 82
5 HASH JOIN OUTER Cost: 30 Bytes: 3 K Cardinality: 82
1 TABLE ACCESS FULL MONITOR.T_PORTAL_TODO_H_SECT Cost: 2 Bytes: 2 K Cardinality: 82
4 VIEW MONITOR. Cost: 27 Bytes: 16 Cardinality: 1
3 SORT GROUP BY Cost: 27 Bytes: 13 Cardinality: 1
2 TABLE ACCESS FULL MONITOR.T_PORTAL_TODO_INFO Cost: 2 Bytes: 13 Cardinality: 1
8 VIEW MONITOR. Cost: 27 Bytes: 16 Cardinality: 1
7 SORT GROUP BY Cost: 27 Bytes: 13 Cardinality: 1
6 TABLE ACCESS FULL MONITOR.T_PORTAL_TODO_INFO Cost: 2 Bytes: 13 Cardinality: 1
12 VIEW MONITOR. Cost: 27 Bytes: 16 Cardinality: 1
11 SORT GROUP BY Cost: 27 Bytes: 13 Cardinality: 1
10 TABLE ACCESS FULL MONITOR.T_PORTAL_TODO_INFO Cost: 2 Bytes: 13 Cardinality: 1
16 VIEW MONITOR. Cost: 27 Bytes: 16 Cardinality: 1
15 SORT GROUP BY Cost: 27 Bytes: 13 Cardinality: 1
14 TABLE ACCESS FULL MONITOR.T_PORTAL_TODO_INFO Cost: 2 Bytes: 13 Cardinality: 1
t_portal_todo_info 表其实有很多的系统类型,字段为systemname
现在想要的效果是用一个多系列柱状图同时显示4个系统的一个访问量,我上面的sql写了4个,
可以理解为默认的,其他的可以在页面上更具用户的选择来动态的现实,也就是说我的 accesstime,systemname两个参数
是从页面传递的,当然每次选择的数量只能是4个,不能多页不能少,时间相同
(
select to_char(accesstime,'HH24') hourpoint,
sum(case when systemname = 'cms' then 1 else 0) a_num,
sum(case when systemname = 'eds' then 1 else 0) b_num,
sum(case when systemname = 'eer' then 1 else 0) c_num,
sum(case when systemname = 'cxpt' then 1 else 0) d_num
from t_portal_todo_info where systemname = 'cms' AND TO_CHAR (accesstime, 'yyyy-MM-dd') = '$searchDate$'
group by to_char(accesstime,'HH24')
) a
, T_PORTAL_TODO_H_SECT e
where a.hourpoint(+) = e.sect
order by e.id
这种形式看上去是比较简单,但不知道统计的数据是否正确,我上面的是麻烦了点,不过已经经过了严格的测试
回公司验证一把,好用就改过来了,谢谢了,有学了一招,不过好像没有解决效率的问题哦。
效率的问题我已经解决了,给字段 accesstime 建了个 to_char() 的函数索引,执行只要 80-100毫秒,
没有索引时需要 20秒,郁闷吧多谢了
所以想把生产机的数据导一份过来,大概有300多万条数据,我导出为
insert 脚本后有80多兆,PL-SQL 好像也不能一下子打开
不知道有没有更好更快速的导入方法,执行脚本我觉得是最普通的
300多万要是执行一下的估计时间也有点让人收不了如果有其他简单快速的方法的话,请简要介绍一下步骤
PL-SQL 或 toad 都可以,最好是 toad,因为我比较熟悉(本人很少用PL-SQL)小弟在此谢过了
在测试机上用import命令导入上一步骤的数据。
imp user/pwd@sid file="f:XX.dmp" tables=(tablename)