select * from (select t1.*, rownum as linenum from (
select /*+ index(a ind_old)*/
a.category from auction_auctions a where a.category =' 170101 ' and a.closed='0' and ends > sysdate and (a.approve_status>=0) order by a.ends) t1 where rownum < 18681) where linenum >= 18641
sql> select segment_name,bytes,blocks from user_segments where segment_name ='auction_auctions';
segment_name bytes blocks
auction_auctions 1059061760 129280
表上原有的索引
create index ind_old on auction_auctions(closed,approve_status,category,ends) tablespace tbsindex compress 2;
sql> select segment_name,bytes,blocks from user_segments where segment_name = 'ind_old';
segment_name bytes blocks
ind_old 20971520 2560
表和索引都已经分析过,我们来看一下sql执行的费用
sql> set autotrace trace;
sql> select * from (select t1.*, rownum as linenum from (select a.* from auction_auctions a where a.category like '18%' and a.closed='0' and ends > sysdate and (a.approve_status>=0) order by a.ends) t1 where rownum <18681) where linenum >= 18641;
select * from (select t1.*, rownum as linenum from (select a.* from auction_auctions a where a.category like '18%' and a.closed='0' and ends > sysdate and (a.approve_status>=0) order by a.ends) t1 where rownum <18681) where linenum >= 18641;
可以看出这个sql语句有很大优化余地,首先最里面的结果集select a.* from auction_auctions a where a.category like '18%' and a.closed='0' and ends > sysdate and (a.approve_status>=0) order by a.ends,这里的话会走index range scan,然后table scan by rowid,这样的话如果符合条件的数据多的话相当耗资源,我们可以改写成
select a.rowid from auction_auctions a where a.category like '18%' and a.closed='0' and ends > sysdate and (a.approve_status>=0) order by a.ends
这样的话最里面的结果集只需要index fast full scan就可以完成了,再改写一下得出以下语句
select * from auction_auctions where rowid in (select rid from (
select t1.rowid rid, rownum as linenum from
(select a.rowid from auction_auctions a where a.category like '18%' and a.closed='0' and ends > sysdate and
(a.approve_status>=0) order by a.ends) t1 where rownum < 18681) where linenum >= 18641)
下面我们来测试一下这个索引的查询开销
select * from auction_auctions where rowid in (select rid from (
select t1.rowid rid, rownum as linenum from
(select a.rowid from auction_auctions a where a.category like '18%' and a.closed='0' and ends > sysdate and
(a.approve_status>=0) order by a.closed,a.ends) t1 where rownum < 18681) where linenum >= 18641)