数据库环境:Oracle
起因:有一张表,业务上要根据时间段,大概一个月的时间段导出Excel。要解决查询太慢问题(以后说其它方面)
背景:当时的查询语句虽然很复杂,当业务有这方面的需求,而且已最大限度的被DB优化过了(包括建索引之类的),似乎没有可优化的空间了。程序中为防止OOM,做了五千条一页的查询。
地点:从小卖部回家的路上
设想:oracle分页是用rownum进行分页的。如果第一页用条件加rownum限制查询逻辑会走一页的数据,但如果查询第二页时,查询逻辑应该会再走一次第一页的数据。(因为要定位到rownum的位置)。
如果我改成区间查询呢,这样即能避免OOM,也能快速定位到查询数据的起始值。
证明:第二天,我进了一些测试,过程如下:
1.查询当月第一天的第一条Id与当月的最后天最后一条Id
minId = query("select min(id) from table where createDate=#{startDate}");
maxId = query("select max(Id) from table where createDate =#{endDAte}")
2.循环查询:
for(i=minId; i< maxId; i+=5000)
{
list = query(select * from table where id > #{i} and id<#{i+5000} )
}
结果:最终证明,这种利用区间查询代替分页的做法,可将查询效率提高了几个级别。特别是数据量很大时,越往后,数据量越大。
疑问:
在实际测试中我发现了,sql中去掉id排序效率也有很明显的提升,照理说,应该不至于如此,如果是mysql因为根据主键组成的聚簇索引的有关系,所以能将查询提升几倍。