Oralce line positioning and rowid:
drop table t purge; create table t as select * from dba_objects; create index idx_object_id on t(object_id); set linesize 1000 set autotrace traceonly - Method 1 (full table scan) select /*+full(t)*/ * from t where object_id=2; - Method 2 (index scan) select * from t where object_id=2; - Method 3 (rowid scanning) set autotrace off select rowid from t where object_id=2; set autotrace traceonly select * from t where object_id=2 and rowid='AAAYiZAALAAAADLAAw'; SQL> select /*+full(t)*/ * from t where object_id=2; -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 207 | 291 (1)| 00:00:04 | |* 1 | TABLE ACCESS FULL| T | 1 | 207 | 291 (1)| 00:00:04 | -------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 1044 consistent gets SQL> select * from t where object_id=2; --------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 207 | 2 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 207 | 2 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | IDX_OBJECT_ID | 1 | | 1 (0)| 00:00:01 | --------------------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 4 consistent gets SQL> select * from t where object_id=2 and rowid='AAAYiZAALAAAADLAAw'; ----------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 219 | 1 (0)| 00:00:01 | |* 1 | TABLE ACCESS BY USER ROWID| T | 1 | 219 | 1 (0)| 00:00:01 | ----------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 1 consistent gets
--- start block size is 2K new tablespace (only 2K, 4K under WINDOWS, 8K and 16K alter system set db_2k_cache_size=100M; drop tablespace tbs_ljb_2k including contents and datafiles; create tablespace TBS_LJB_2k blocksize 2K datafile 'D:\ORACLE\ORADATA\TEST11G\TBS_LJB_2K_01.DBF' size 100M autoextend on extent management local segment space management auto; create table t_2k tablespace tbs_ljb_2k as select * from dba_objects; --- start block size is 4K new tablespace alter system set db_4k_cache_size=100M; drop tablespace tbs_ljb_4k including contents and datafiles; create tablespace TBS_LJB_4k blocksize 4K datafile 'D:\ORACLE\ORADATA\TEST11G\TBS_LJB_4K_01.DBF' size 100M autoextend on extent management local segment space management auto; create table t_4k tablespace tbs_ljb_4k as select * from dba_objects; --- Start of block sizes of 8K New Table space (default is 8K) drop table t_8k purge; create table t_8k as select * from dba_objects; --- start block size of 16K new tablespace alter system set db_16k_cache_size=100M; drop tablespace tbs_ljb_16k including contents and datafiles; create tablespace TBS_LJB_16k blocksize 16K datafile 'D:\ORACLE\ORADATA\TEST11G\TBS_LJB_16K_01.DBF' size 100M autoextend on extent management local segment space management auto; create table t_16k tablespace tbs_ljb_16k as select * from dba_objects; ----------------------------------------------------------------------------------------- - Start the test and found that costs and fewer logical reads all this! SET autotrace traceonly select count(*) from t_2k; / select count(*) from t_4k; / select count(*) from t_8k; / select count(*) from t_16k; / - but it is not block the bigger the better, pay attention to the hot block competition. SQL> select count(*) from t_2k; ------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 891 (1)| 00:00:11 | | 1 | SORT AGGREGATE | | 1 | | | | 2 | TABLE ACCESS FULL| T_2K | 83292 | 891 (1)| 00:00:11 | ------------------------------------------------------------------- Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 4511 consistent gets SQL> select count(*) from t_4k; ------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 480 (1)| 00:00:06 | | 1 | SORT AGGREGATE | | 1 | | | | 2 | TABLE ACCESS FULL| T_4K | 63139 | 480 (1)| 00:00:06 | ------------------------------------------------------------------- Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 2137 consistent gets SQL> select count(*) from t_8k; ------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 291 (1)| 00:00:04 | | 1 | SORT AGGREGATE | | 1 | | | | 2 | TABLE ACCESS FULL| T_8K | 62320 | 291 (1)| 00:00:04 | ------------------------------------------------------------------- Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 1043 consistent gets SQL> select count(*) from t_16k; -------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 200 (1)| 00:00:03 | | 1 | SORT AGGREGATE | | 1 | | | | 2 | TABLE ACCESS FULL| T_16K | 80144 | 200 (1)| 00:00:03 | -------------------------------------------------------------------- Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 517 consistent gets
- Oracle system block size view sqlplus "/ as sysdba" show parameter db_block_size select block_size from dba_tablespaces where tablespace_name='SYSTEM'; --- start a new block of size 2K tablespace (only 2K under WINDOWS, 4K, 8K and 16K) alter system set db_2k_cache_size=100M; drop tablespace tbs_ljb_2k including contents and datafiles; create tablespace TBS_LJB_2k blocksize 2K datafile 'D:\ORACLE\ORADATA\TEST11G\TBS_LJB_2K_01.DBF' size 100M autoextend on extent management local segment space management auto; create table t_2k tablespace tbs_ljb_2k as select * from dba_objects where rownum<=100; --- start block size is 4K new tablespace alter system set db_4k_cache_size=100M; drop tablespace tbs_ljb_4k including contents and datafiles; create tablespace TBS_LJB_4k blocksize 4K datafile 'D:\ORACLE\ORADATA\TEST11G\TBS_LJB_4K_01.DBF' size 100M autoextend on extent management local segment space management auto; create table t_4k tablespace tbs_ljb_4k as select * from dba_objects where rownum<=100; --- Start of block sizes of 8K New Table space (default is 8K) drop table t_8k purge; create table t_8k as select * from dba_objects where rownum<=100; --- start block size of 16K new tablespace alter system set db_16k_cache_size=100M; drop tablespace tbs_ljb_16k including contents and datafiles; create tablespace TBS_LJB_16k blocksize 16K datafile 'D:\ORACLE\ORADATA\TEST11G\TBS_LJB_16K_01.DBF' size 100M autoextend on extent management local segment space management auto; create table t_16k tablespace tbs_ljb_16k as select * from dba_objects where rownum<=100; - The larger the block before tried, the less logical reads, but the reality is not block the bigger the better, but also pay attention to the hot block competition. ------------------------------------------------------------------------------------------------------------------------------------------- sqlplus "/ as sysdba" grant all on DBMS_LOCK to ljb; connect ljb/ljb - create a package to construct various JOB, analyze problems create or replace package pkg_test_block_size as procedure p_t_2k; procedure p_t_4k; procedure p_t_8k; procedure p_t_16k; procedure p_exec_2k_job; procedure p_exec_4k_job; procedure p_exec_8k_job; procedure p_exec_16k_job; procedure p_remove_job; end pkg_test_block_size; / create or replace package body pkg_test_block_size as procedure p_t_2k as begin for j in 1..1000 loop for i in (select * from t_2k ) loop null; end loop; end loop; end p_t_2k; procedure p_t_4k as begin for j in 1..1000 loop for i in (select * from t_4k ) loop null; end loop; end loop; end p_t_4k; procedure p_t_8k as begin for j in 1..1000 loop for i in (select * from t_8k ) loop null; end loop; end loop; end p_t_8k; procedure p_t_16k as begin for j in 1..1000 loop for i in (select * from t_16k ) loop null; end loop; end loop; end p_t_16k; - Create JOB procedure p_exec_2k_job as JOBNO NUMBER; BEGIN for i in 1..100 loop DBMS_JOB.SUBMIT( JOBNO, 'pkg_test_block_size.p_t_2k;', SYSDATE, 'SYSDATE+1/1440'); end loop; DBMS_LOCK.sleep(120); END p_exec_2k_job; procedure p_exec_4k_job as JOBNO NUMBER; BEGIN for i in 1..100 loop DBMS_JOB.SUBMIT( JOBNO, 'pkg_test_block_size.p_t_4k;', SYSDATE, 'SYSDATE+1/1440'); end loop; DBMS_LOCK.sleep(120); END p_exec_4k_job; procedure p_exec_8k_job as JOBNO NUMBER; BEGIN for i in 1..100 loop DBMS_JOB.SUBMIT( JOBNO, 'pkg_test_block_size.p_t_8k;', SYSDATE, 'SYSDATE+1/1440'); end loop; DBMS_LOCK.sleep(120); END p_exec_8k_job; procedure p_exec_16k_job as JOBNO NUMBER; BEGIN for i in 1..100 loop DBMS_JOB.SUBMIT( JOBNO, 'pkg_test_block_size.p_t_16k;', SYSDATE, 'SYSDATE+1/1440'); end loop; DBMS_LOCK.sleep(120); END p_exec_16k_job; procedure p_remove_job as BEGIN for i in (select job from user_jobs )loop DBMS_JOB.remove(i.job); end loop; END p_remove_job; END pkg_test_block_size; drop table test_latch purge; create table test_latch (block_size varchar2(10),id number,gets number , misses number, sleeps number, immediate_gets number); - Test 1. delete from test_latch where block_size='2k'; insert into test_latch select '2k',1,gets,misses,sleeps,immediate_gets from v$latch where name='cache buffers chains'; commit; --exec dbms_workload_repository.create_snapshot(); exec pkg_test_block_size.p_exec_2k_job; --exec dbms_workload_repository.create_snapshot(); insert into test_latch select '2k',2,gets,misses,sleeps,immediate_gets from v$latch where name='cache buffers chains'; commit; - end of the test exec pkg_test_block_size.p_remove_job; --@?/rdbms/admin/awrrpt.sql - Test 2. delete from test_latch where block_size='4k'; insert into test_latch select '4k',1,gets,misses,sleeps,immediate_gets from v$latch where name='cache buffers chains'; commit; --exec dbms_workload_repository.create_snapshot(); exec pkg_test_block_size.p_exec_4k_job; --exec dbms_workload_repository.create_snapshot(); insert into test_latch select '4k',2,gets,misses,sleeps,immediate_gets from v$latch where name='cache buffers chains'; commit; - end of the test exec pkg_test_block_size.p_remove_job; --@?/rdbms/admin/awrrpt.sql - Test 3. delete from test_latch where block_size='8k'; insert into test_latch select '8k',1,gets,misses,sleeps,immediate_gets from v$latch where name='cache buffers chains'; commit; --exec dbms_workload_repository.create_snapshot(); exec pkg_test_block_size.p_exec_8k_job; --exec dbms_workload_repository.create_snapshot(); insert into test_latch select '8k',2,gets,misses,sleeps,immediate_gets from v$latch where name='cache buffers chains'; commit; - end of the test exec pkg_test_block_size.p_remove_job; --@?/rdbms/admin/awrrpt.sql - Test 4. delete from test_latch where block_size='16k'; insert into test_latch select '16k',1,gets,misses,sleeps,immediate_gets from v$latch where name='cache buffers chains'; commit; --exec dbms_workload_repository.create_snapshot(); exec pkg_test_block_size.p_exec_16k_job; --exec dbms_workload_repository.create_snapshot(); insert into test_latch select '16k',2,gets,misses,sleeps,immediate_gets from v$latch where name='cache buffers chains'; commit; - end of the test exec pkg_test_block_size.p_remove_job; --@?/rdbms/admin/awrrpt.sql SELECT WHAT, INTERVAL, JOB, NEXT_DATE, NEXT_SEC, FAILURES, BROKEN FROM USER_JOBS WHERE INTERVAL = 'SYSDATE+1/1440'; select * from v$latch_children where name='cache buffers chains' select * from test_latch; - The following results are for reference only, actual implementation may be due to the amount of data is not large enough, concurrency is not big enough, but there are differences. select block_size, misses - lag_misses from (select t.*,lag(misses) over(partition by block_size order by misses) lag_misses from test_latch t) k where k.lag_misses is not null; BLOCK_SIZE MISSES-LAG_MISSES ---------- ------------------ 2k 0 4k 47 407 8K 67769 16k 86871 Observed: select t.*, s.sid, s.serial#, s.machine, s.program, s.osuser from (select c.USERNAME, a.event, a.cnt as "TIME(SECOND)", a.sql_id, b.sql_fulltext from (select rownum rn, t.* from (select decode(s.session_state, 'WAITING', s.event, 'Cpu + Wait For Cpu') Event, s.sql_id, s.user_id, count(*) CNT from v$active_session_history s where sample_time > sysdate - 15 / 1440 group by s.user_id, decode(s.session_state, 'WAITING', s.event, 'Cpu + Wait For Cpu'), s.sql_id order by CNT desc) t where rownum < 20) a, v$sqlarea b, dba_users c where a.sql_id = b.sql_id and a.user_id = c.user_id order by CNT desc) t, v$session s where t.sql_id = s.sql_id(+);