|
atgc 发表于 2012-4-20 09:17 ![]()
consistent gets值大不, 并不等于就一定慢,如果排序分页需要提取所有字段,显然是ROWID分页快
SQL> sel ...
此帖主要目的是揭露一个一直被忽略的11g新特性。11g得益于这个新特性,rowid分页基本普遍优于rownum分页。
而在10g中由于没有这个特性,那么要考虑的就很多了。
页后翻的页数,以及页的大小,以及行的长度,以及集群因子,都可能决定了rownum和rowid谁的性能更好。
所以也可以通过调整:页数,页大小,行长度,集群因子 这些参数,来构造不同的实验得到不同结果。
譬如:
select /*+ ordered use_nl(p s) */ *
from (
select rownum rn,rd
from (select rowid rd from test order by created)
t where rownum<8000) p,
test s
where rn>7000 and p.rd=s.rowid; swp1 >swp1 > 2 3 4 5 6 7
999 rows selected.
Elapsed: 00:00:00.03
Execution Plan
----------------------------------------------------------
Plan hash value: 827357089
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 7999 | 437K| 8321 (1)| 00:01:57 |
| 1 | NESTED LOOPS | | 7999 | 437K| 8321 (1)| 00:01:57 |
|* 2 | VIEW | | 7999 | 195K| 316 (1)| 00:00:05 |
|* 3 | COUNT STOPKEY | | | | | |
| 4 | VIEW | | 182K| 2138K| 316 (1)| 00:00:05 |
| 5 | INDEX FULL SCAN | TEST_IND1 | 182K| 3385K| 316 (1)| 00:00:05 |
| 6 | TABLE ACCESS BY USER ROWID| TEST | 1 | 31 | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("RN">7000)
3 - filter(ROWNUM<8000)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
1081 consistent gets
0 physical reads
0 redo size
49093 bytes sent via SQL*Net to client
1218 bytes received via SQL*Net from client
68 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
999 rows processed
swp1 >select *
from (
select rownum rn,t.*
from
(select id,status,type,created from test2 order by created) t
where rownum<8000)
where rn >7000; 2 3 4 5 6 7
999 rows selected.
Elapsed: 00:00:00.01
Execution Plan
----------------------------------------------------------
Plan hash value: 1795700156
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 7999 | 398K| 30 (0)| 00:00:01 |
|* 1 | VIEW | | 7999 | 398K| 30 (0)| 00:00:01 |
|* 2 | COUNT STOPKEY | | | | | |
| 3 | VIEW | | 7999 | 296K| 30 (0)| 00:00:01 |
| 4 | TABLE ACCESS BY INDEX ROWID| TEST2 | 182K| 4455K| 30 (0)| 00:00:01 |
| 5 | INDEX FULL SCAN | TEST2_IND1 | 7999 | | 12 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("RN">7000)
2 - filter(ROWNUM<8000)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
163 consistent gets
0 physical reads
0 redo size
31838 bytes sent via SQL*Net to client
1218 bytes received via SQL*Net from client
68 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
999 rows processed
可以看到我构造的这个结果:
rowid rownum
时间: 00.03 00.01
块读: 1081 163
此外,更重要的一点就是,关于你的看执行时间不看 块读 的做法我不认同。
一是因为在我们的实验中全部都是逻辑读。
而要知道,在真正的环境中,这种全表的块读是很容易产生物理读的,而常常多一个物理读的开销就能抵得上千百个逻辑读。
二是因为大部分的系统瓶颈都在IO
|
|