rowid paging benefit from 11g new feature
rowid paging benefit from 11g new feature
http://dbakevin.blogspot.com/2012/04/rowid-paging-benifit-from-11g-new.html
Need proxy to access the URL above -- http://www.51proxied.com/
Consider below request:
We need to get the 900 to 1000 records after ordered by time.
We call this kind of request as "paging". Because in most case we encounter this kind of request in web page's redirect buttons: page 1, page 2, page 3.....
We can jump to any page via clicking the conrrespoding buttion.
There are two kinds of paging method in oracle: Rownum paging and Rowid paging.
Almost all the documents which i read all announce that rowid is a better method then rownum for paging.
They said:
For the first a few pages, two methods have similiar performance.But as long as the page number become bigger and bigger, rowid paging perform better and better then rownum paging.
Pay attention to the red part. Is that really true? Let's make a experiment.
First test in 11g. Create test table as below:
11gR2 >create table test(id number,status VARCHAR2(7),type VARCHAR2(19),created date); Table created. 11gR2 >insert into test select OBJECT_ID,STATUS,OBJECT_TYPE,CREATED from dba_objects; 12926 rows created. 11gR2 >alter table test modify created not null; Table altered. 11gR2 >create index test_ind1 on test(CREATED); Index created. 11gR2 >ANALYZE TABLE TEST compute statistics; Table analyzed.
We are going to read row 900-1000 from table test order by created.
Test 11g paging with rownum method:
11gR2 >select * from ( select rownum rn,t.* from (select id,status,type,created from test order by created) t where rownum<1000) where rn >900; 99 rows selected. -------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 999 | 50949 | 9 (0)| 00:00:01 | |* 1 | VIEW | | 999 | 50949 | 9 (0)| 00:00:01 | |* 2 | COUNT STOPKEY | | | | | | | 3 | VIEW | | 999 | 37962 | 9 (0)| 00:00:01 | | 4 | TABLE ACCESS BY INDEX ROWID| TEST | 12926 | 277K| 9 (0)| 00:00:01 | | 5 | INDEX FULL SCAN | TEST_IND1 | 999 | | 4 (0)| 00:00:01 | -------------------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 22 consistent gets 0 physical reads 0 redo size 3703 bytes sent via SQL*Net to client 590 bytes received via SQL*Net from client 8 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 99 rows processed
Test 11g paging with rowid method:
11gR2 >select /*+ ordered use_nl(p s) */ * from ( select rownum rn,rd from (select rowid rd from test order by created) t where rownum<1000) p, test s where rn>900 and p.rd=s.rowid; 2 3 4 5 6 7 99 rows selected. ----------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ----------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 999 | 52947 | 1003 (0)| 00:00:13 | | 1 | NESTED LOOPS | | 999 | 52947 | 1003 (0)| 00:00:13 | |* 2 | VIEW | | 999 | 24975 | 4 (0)| 00:00:01 | |* 3 | COUNT STOPKEY | | | | | | | 4 | VIEW | | 999 | 11988 | 4 (0)| 00:00:01 | | 5 | INDEX FULL SCAN | TEST_IND1 | 12926 | 239K| 4 (0)| 00:00:01 | | 6 | TABLE ACCESS BY USER ROWID| TEST | 1 | 28 | 1 (0)| 00:00:01 | ----------------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 19 consistent gets 0 physical reads 0 redo size 5450 bytes sent via SQL*Net to client 590 bytes received via SQL*Net from client 8 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 99 rows processed
From the red part we can see rowid paging(19 logic read) do better then rownum paging(22 logic read).
The reason is rowid method reduce the "TABLE ACCESS BY ROWID" for first 900 rows.
Let's check in 10g:
Build the Test table as excatly the same with 11g, created the index and gathered stats.
Test 10g paging with rownum method:
10gR2 >select * from ( select rownum rn,t.* from (select id,status,type,created from test order by created) t where rownum<1000) where rn >900; 99 rows selected. -------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 999 | 50949 | 17 (0)| 00:00:01 | |* 1 | VIEW | | 999 | 50949 | 17 (0)| 00:00:01 | |* 2 | COUNT STOPKEY | | | | | | | 3 | VIEW | | 999 | 37962 | 17 (0)| 00:00:01 | | 4 | TABLE ACCESS BY INDEX ROWID| TEST | 45620 | 1113K| 17 (0)| 00:00:01 | | 5 | INDEX FULL SCAN | TEST_IND1 | 999 | | 3 (0)| 00:00:01 | -------------------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 19 consistent gets 0 physical reads 0 redo size 3842 bytes sent via SQL*Net to client 558 bytes received via SQL*Net from client 8 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 99 rows processed
19 logic read, very close to 11g. It is a normal value and close to our expected.
Test 10g paging with rowid method:
10gR2 >select /*+ ordered use_nl(p s) */ * from ( select rownum rn,rd from (select rowid rd from test order by created) t where rownum<200) p, test s where rn>100 and p.rd=s.rowid; 99 rows selected. ----------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ----------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 199 | 11144 | 261 (1)| 00:00:04 | | 1 | NESTED LOOPS | | 199 | 11144 | 261 (1)| 00:00:04 | |* 2 | VIEW | | 199 | 4975 | 62 (2)| 00:00:01 | |* 3 | COUNT STOPKEY | | | | | | | 4 | VIEW | | 45620 | 534K| 62 (2)| 00:00:01 | | 5 | INDEX FULL SCAN | TEST_IND1 | 45620 | 846K| 62 (2)| 00:00:01 | | 6 | TABLE ACCESS BY USER ROWID| TEST | 1 | 31 | 1 (0)| 00:00:01 | ----------------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 108 consistent gets 0 physical reads 0 redo size 5252 bytes sent via SQL*Net to client 558 bytes received via SQL*Net from client 8 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 99 rows processed
wow, why logic turn to 108? The execution plan is same with 11g, but why so big difference in logic read?
rownum rowid
11g: 22 19
10g: 19 108
Why?
Below is the Reason:
11gR2 >select rowid,id from test where rowid in ('AAADSHAABAAAH3hAAA','AAADSHAABAAAH3hAAB','AAADSHAABAAAH3hAAC','AAADSHAABAAAH3hAAD','AAADSHAABAAAH3hAAE','AAADSHAABAAAH3hAAF','AAADSHAABAAAH3hAAG','AAADSHAABAAAH3hAAH','AAADSHAABAAAH3hAAI','AAADSHAABAAAH3hAAJ'); ROWID ID ------------------ ---------- AAADSHAABAAAH3hAAA 20 AAADSHAABAAAH3hAAB 46 AAADSHAABAAAH3hAAC 28 AAADSHAABAAAH3hAAD 15 AAADSHAABAAAH3hAAE 29 AAADSHAABAAAH3hAAF 3 AAADSHAABAAAH3hAAG 25 AAADSHAABAAAH3hAAH 41 AAADSHAABAAAH3hAAI 54 AAADSHAABAAAH3hAAJ 40 10 rows selected. Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 2 consistent gets 0 physical reads 0 redo size 875 bytes sent via SQL*Net to client 524 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 10 rows processed 10gR2 >select rowid,id from test where rowid in ('AAAzo5AABAAAKnWAAA','AAAzo5AABAAAKnWAAB','AAAzo5AABAAAKnWAAC','AAAzo5AABAAAKnWAAD','AAAzo5AABAAAKnWAAE','AAAzo5AABAAAKnWAAF','AAAzo5AABAAAKnWAAG','AAAzo5AABAAAKnWAAH','AAAzo5AABAAAKnWAAI','AAAzo5AABAAAKnWAAJ'); ROWID ID ------------------ ---------- AAAzo5AABAAAKnWAAA 30 AAAzo5AABAAAKnWAAB 8 AAAzo5AABAAAKnWAAC 14 AAAzo5AABAAAKnWAAD 34 AAAzo5AABAAAKnWAAE 45 AAAzo5AABAAAKnWAAF 39 AAAzo5AABAAAKnWAAG 47 AAAzo5AABAAAKnWAAH 51 AAAzo5AABAAAKnWAAI 11 AAAzo5AABAAAKnWAAJ 48 10 rows selected. Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 10 consistent gets 0 physical reads 0 redo size 861 bytes sent via SQL*Net to client 492 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 10 rows processed
A Rowid is made by: OOOOOOFFFBBBBBBRRR
O is object id,F is file id,B is block id,R is row number.
From above we can see, read 10 rows from same block in 11g cost 2 block read while in 10g cost 10 block read.
Further research also confirmed in 10g, every rowid will gernerate an logic read, even all the rowid are come from same block.
But in 11g some new machanism are introduced, if next rowid is in the same block with current row, then current block can be reuse.
--------------------------------------
Regards,
FangwenYu
![](https://pic.cnblogs.com/avatar/93867/20191016181427.png)