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)