项目总结2

 通过去年做的一个项目我体会到,数据量大了以后,看似简单的问题都变得让人寝食难安,在解决问题的过程中收集了不少好文章,集中在此,方便自己查阅。

oracle 9i 数据库设计指引全集(1)         oracle 9i 数据库设计指引全集(2)    oracle 9i 数据库设计指引全集(3)

oracle 9i 数据库设计指引全集(4)         oracle 分区表的建立方法             关于oracle表空间的规划方法

关于Oracle数据库中索引的维护经验谈    Oracle 分区索引详解             何时使用绑定变量性能反而差

ORACLE 中ROWNUM用法总结

      先说一下项目的情况,做的是一个治安卡口软件,在进出城市的主要路口安装摄像机,记录过往车辆的相关信息(车牌号码、通过时间、车速等等),把采集到的车辆信息传至中心服务器存储,供相关业务部门进行布控、查询、违法处罚等,业务很简单,就是数据量巨大(想想一个路口一天要过多少车,10个路口,20个......)业主要求保留近3个月的记录.

系统在运行了过程中,随着数据量的增加,问题不断的出现,2000万、4000万......每次都是一次折磨

一个功能是按照一些条件对过往车辆进行查询,由于过往车辆表的数据库太大,查询的响应时间成了大问题
下面是遇到的一些问题:

1. 限制一次可以查询的最多记录数

我的办法是根据计算记录总数,得到记录总数后生成分页导航,再载入当前页数据。
利用rownum进行分页,分页的办法:
select * 
from (selet rownum as  rn,t.* from t where ...)
where rn > pageleft and rn <=pageright  

在开发阶段由于测试环境的数据量很小,没出现什么问题,到了实际环境问题来了,用户查询一段时间通过的车辆,计算个记录总数就需要很长时间,我自己都不能忍受,更不用说用户了。

找点理由:即使我把这几十万、上百万的记录返回给了,有什么用呢?用户需要的是尽量精确的记录,返回的记录数越少越有价值,用户不会在几十万条记录中一条一条的去找。所以可以限制一次能够查询的记录总数,比如只返回前1万条;

郁闷的同时我也在想:google是怎么做分页?

从google的搜索结果中我注意到两点:
1.顶部给出的查询结果总数不是精确值,而是“约有…” ,不是即时计算的。

2.如果查询1000条后的记录,修改url中的start后的参数:
http://www.google.cn/search?hl=zh-CN&newwindow=1&q=dudu&start=1001&sa=N
会出现“对不起,Google 为所有查询的结果数都不会超过 1000 个。 (您所请求的结果在第 1001 个之后。)”

了解到了这些,我理直气壮的跟用户说:我要限制一次能够返回的记录的数量。

于是修改为:
select * 
from (selet rownum as  rn,t.* from t where ... and rownum < maxRow )
where rn > pageleft and rn <=pageright

修改后的查询比以前快了一些,我想了想,其实不用rownum<maxRow 只要  
select * 
from (selet rownum as  rn,t.* from t where ... and rownum <= pagerright)
where rn >= pageleft and rn < pageright  即可,

修改后再试,又快了一些;发现翻页时,随着页码的增加,响应时间也逐渐增大,这是肯定的了,rownum<=10和rownum<=1000肯定不一样的了。

2. 不计算count

      过了一两个月,用户又打电话来了,说有些组合条件查询很慢,甚至没有响应。到现场看看,查一下现在有多少数据,执行了个select count(*) ,竟然等了十几分钟才出来结果,记录数是3500多万条,后来调试程序,发现真正取得一页数据还是比较快的,耗费时间的操作是计算记录总数,把sql语句直接放到pl sql 中执行也需要几分钟才能出来结果,靠,这个select count 要这么长时间,算了,不计算查询结果的总数了。不计算记录总数,还要分页,想了一些办法解决了。修改后查询速度快了很多,这两个月通过对oracle的学习,俺已经认识到这么大的数据量应该对主表进行分区了。

3. 按照时间对主表进行分区

     按照时间对过往车辆表进行分区无疑是最合适的。
    如果一个月建一个分区,我可以预先建出来未来半年或一年的分区,例如2008-07-01 00:00:00 到2008-08-01 00:00:00 之间的记录在一个分区,2008-08-01 00:00:00 到2008-09-01 00:00:00 之间的记录又是一个分区;这样做的问题是过半年我需要到现场再创建以后的分区,删除以前作废的分区,不是个好办法。
    最后想到的办法是按照月份建12个分区,按照记录的时间字段所在的月份映射到对应的月份分区。不管是08年7月的还是09年7月的记录,均映射到7月的分区。
    按照月份分区后,效果很明显。 

4. 定期对表进行统计分析  

5. 一个教训是:使用绑定变量方式和直接赋值方式的执行计划可能是不一样的;当发现某个查询的速度比预期的慢的很多,很可能是sql语句执行时使用了错误的查询计划,这个时候就需要去查找原因了。

6.数据量大,增长快,数据的备份也不容易了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值