果然视图的效率永远是跟不上表的啊

工作上的原因开始接触Oracle了...虽然Oracle在几年前就玩过了,但是基本上都是最基本得操作了,简单的存储过程,简单的触发器.....

现在到了新的公司,碰到了诡异的问题是一个针对地区的统计问题.

一个省下面有许多的市,需要统计这些市出现的次数,以及外省的数字.

本来这个是一个非常容易搞定的问题,但是现在却碰到了麻烦,那就是这个地址字段里面存放的并不是地区的代码而是地区的文本....orz

于是现在如果想要统计这种要么通过不断的LIKE来做Count(ID),然后UNION ALL形成最终结果了...但是仅仅面对20万左右的数据量,这条语句的执行时间居然长达3分钟以上.

然后想了一个办法,首先将所有符合条件的数据全部用视图的方式UNION ALL起来,添加一个虚拟的地区代码字段,然后再对这个视图做Group BY操作.

可惜,就算是这样做了,也仅仅只是把时间提升到了2分钟10秒左右.

没办法,只有想办法改动表结构了...我是一直不怎么想改动这个表结构的,因为不是我设计的,而且本身设计的很糟糕... 程序也是刚刚接手,都没办法整理,所以如果变动了表结构,就一定要通过触发器来解决后续的问题了...

不过抱着尝试的心态,添加了一个字段,然后简单的用LIKE来更新这个字段.

然后再用Group By来生成报表.这时惊人的效率提升终于出现了..只用了5秒.

但是只有20万的数据量的话,用5秒似乎也显得太多了一点 ,估计是没有使用到索引...

于是添加索引,以Where语句的字段和Group By后面的字段添加联合索引.再做测试...

速度终于提升到0.15秒左右了...正常范围内了(虽然赶不上MySQL的效率了,当然,这也是必然的)...

接下来就是触发器了...以前只是写过一个自增ID字段的触发器而已,而且还是网上直接抄下来的...

不过现在这个触发器也很简单就是了...所需要实现的就是在Insert字段的时候根据既有的字段中的某一个值(所在地区)得取值来确定我添加的那个字段的取值.并且将更新了的数据插入进去就可以了.

但是不得不说,我根本就忘了触发器怎么写了....orz

不过最后还是搞定了就是了...之前忘掉了使用for each row,导致一直都报告ORA-04082错误,添加那个字段后终于搞定了...这个字段的含义是,缺省的触发器是语句级别的,如果添加了这个字段就会变成行级别,可以对语句所涉及到的每一行都做操作,对于Insert而言,这自然就是对刚刚Insert进来的这一行了...

最终的样子如下:
create OR REPLACE trigger BI_ACCEPT
       before Insert
              on WX_ACCEPT
for each row
Begin
  if :new.APPEAL_ADDRESS LIKE '%武汉%' then
    :new.LOCATION_NAME := 1;
  elsif :new.APPEAL_ADDRESS LIKE '%黄石%' then
    :new.LOCATION_NAME := 2;
  elsif :new.APPEAL_ADDRESS LIKE '%十堰%' then
    :new.LOCATION_NAME := 3;
  elsif :new.APPEAL_ADDRESS LIKE '%宜昌%' then
    :new.LOCATION_NAME := 4;
  elsif :new.APPEAL_ADDRESS LIKE '%襄樊%' OR :new.APPEAL_ADDRESS LIKE '%襄阳%' then
    :new.LOCATION_NAME := 5;
  elsif :new.APPEAL_ADDRESS LIKE '%鄂州%' then
    :new.LOCATION_NAME := 6;
  elsif :new.APPEAL_ADDRESS LIKE '%荆门%' then
    :new.LOCATION_NAME := 7;
  elsif :new.APPEAL_ADDRESS LIKE '%孝感%' then
    :new.LOCATION_NAME := 8;
  elsif :new.APPEAL_ADDRESS LIKE '%荆州%' then
    :new.LOCATION_NAME := 9;
  elsif :new.APPEAL_ADDRESS LIKE '%黄冈%' then
    :new.LOCATION_NAME := 10;
  elsif :new.APPEAL_ADDRESS LIKE '%咸宁%' then
    :new.LOCATION_NAME := 11;
  elsif :new.APPEAL_ADDRESS LIKE '%随州%' then
    :new.LOCATION_NAME := 12;
  elsif :new.APPEAL_ADDRESS LIKE '%恩施%' then
    :new.LOCATION_NAME := 13;
  elsif :new.APPEAL_ADDRESS LIKE '%仙桃%' then
    :new.LOCATION_NAME := 14;
  elsif :new.APPEAL_ADDRESS LIKE '%潜江%' then
    :new.LOCATION_NAME := 15;
  elsif :new.APPEAL_ADDRESS LIKE '%天门%' then
    :new.LOCATION_NAME := 16;
  elsif :new.APPEAL_ADDRESS LIKE '%神农架%' then
    :new.LOCATION_NAME := 17;
  end if;
end;

评论

此博客中的热门博文

远程记录OpenWRT日志

用OpenWRT打造自动翻墙路由器(详解篇)

转一下关于Fuck的用法