问题:
有一个批量操作,需要依次更新一个大表的大部分数据,而数据库buffer cache足够大,可以容纳该表.
是否可以通过并行全表扫描(db scattered read)将该表读入buffer cache,避免单块读取(db sequential read)导致的大量物理IO?
后者物理读次数是前者物理读次数的db_file_multiblock_read_count(缺省为16)倍.
为了验证该方案,需要明确如下问题,在全表扫描时:
(1)将表的数据块缓存到buffer cache还是PGA?是否使用多块读?
(2)使用parallel提示情况下,缓存到buffer cache还是PGA?是否使用多块读?
1 测试表准备
create table t
as
select * from dba_objects;
Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0
Connected as pg@dev95
SQL>
SQL> select bytes,blocks,extents from user_segments where segment_name='T';
BYTES BLOCKS EXTENTS
---------- ---------- ----------
9437184 1152 24
SQL> select extent_id,bytes,blocks from user_extents where segment_name='T';
EXTENT_ID BYTES BLOCKS
---------- ---------- ----------
0 65536 8
1 65536 8
2 65536 8
3 65536 8
4 65536 8
5 65536 8
6 65536 8
7 65536 8
8 65536 8
9 65536 8
10 65536 8
11 65536 8
12 65536 8
13 65536 8
14 65536 8
15 65536 8
16 1048576 128
17 1048576 128
18 1048576 128
19 1048576 128
20 1048576 128
21 1048576 128
22 1048576 128
23 1048576 128
24 rows selected
SQL> select object_id,data_object_id from user_objects where object_name='T';
OBJECT_ID DATA_OBJECT_ID
---------- --------------
155073 155073
SQL> select file#,block#,class#,status from v$bh where bjd=155073;
FILE# BLOCK# CLASS# STATUS
---------- ---------- ---------- -------
6 253578 8 xcur
16 56457 8 xcur
12 30649 8 xcur
15 57481 8 xcur
12 30665 8 xcur
20 26890 8 xcur
19 23306 8 xcur
15 57497 8 xcur
12 30681 8 xcur
18 44682 8 xcur
12 30634 9 xcur
7 160905 8 xcur
12 30697 8 xcur
17 555273 8 xcur
16 56458 8 xcur
8 126217 8 xcur
12 30713 8 xcur
6 253577 8 xcur
12 30635 4 xcur
7 160906 8 xcur
17 555274 8 xcur
20 26889 8 xcur
19 23305 8 xcur
8 126218 8 xcur
18 44681 8 xcur
12 30633 8 xcur
26 rows selected
2 全表扫描缓存到buffer cache还是pga?是否使用多块读?
结论:缓存到buffer cache;使用了多块读。
SQL>
SQL> alter system flush shared_pool;
System altered
SQL> alter system flush buffer_cache;
System altered
SQL>
SQL>
SQL> select status, count(*) from v$bh where bjd = 155073 group by status;
free 1026
SQL> select statistic_name,value
2 from v$segment_statistics ss
3 where wner = user
4 and object_name = 'T'
5 and value>0
6 order by 2;
segment scans 1
db block changes 256
physical writes direct 1125
physical reads 1126
physical writes 1151
logical reads 2704
space used 9216000
space allocated 9437184
8 rows selected
SQL> select sid, name, value
2 from v$mystat ses, v$statname sn
3 where ses.STATISTIC# = sn.STATISTIC#
4 and value > 0
5 and name like '%read%'
6 order by 3;
822 physical read total multi block requests 95
822 physical read total IO requests 694
822 physical read IO requests 694
822 physical reads cache prefetch 1018
822 physical reads 1712
822 physical reads cache 1712
822 no work - consistent read gets 641666
822 session logical reads 1094037
822 physical read total bytes 14024704
822 physical read bytes 14024704
10 rows selected
SQL> select event, total_waits
2 from v$session_event
3 where sid = 822
4 and wait_class = 'User I/O'
5 order by 1;
db file scattered read 95
db file sequential read 606
SQL> select count(*) from t;
80677
SQL> select sql_id,disk_reads,direct_writes,user_io_wait_time,buffer_gets,sql_text from v$sql where sql_text like '%count(*) from t%';
a3uxj45fdjv7m 1128 0 69853 1199 select count(*) from t
==〉v$sql.disk_reads:Number of disk reads for this child cursor
SQL> select * from table(dbms_xplan.display_cursor('a3uxj45fdjv7m'));
SQL_ID a3uxj45fdjv7m, child number 0
-------------------------------------
select count(*) from t
Plan hash value: 2966233522
-------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | 93 (100)| |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| T | 80442 | 93 (3)| 00:00:01 |
-------------------------------------------------------------------
Note
-----
- dynamic sampling used for this statement
18 rows selected
SQL> select status, count(*) from v$bh where bjd = 155073 group by status;
xcur 1126 free 788
cr 1
==〉xcur:1126,说明缓存到了buffer cache
SQL> select statistic_name,value
2 from v$segment_statistics ss
3 where wner = user
4 and object_name = 'T'
5 and value>0
6 order by 2;
segment scans 1
db block changes 256
physical writes direct 1125
physical writes 1151
physical reads 2252 logical reads 3904
space used 9216000
space allocated 9437184
8 rows selected
SQL> select sid, name, value
2 from v$mystat ses, v$statname sn
3 where ses.STATISTIC# = sn.STATISTIC#
4 and value > 0
5 and name like '%read%'
6 order by 3;
822 physical read total multi block requests 189 822 physical read total IO requests 822 822 physical read IO requests 822 822 physical reads cache prefetch 2032 822 physical reads 2854 822 physical reads cache 2854 822 no work - consistent read gets 648919
822 session logical reads 1107445
822 physical read total bytes 23379968
822 physical read bytes 23379968
==〉physical read total multi block requests:94,说明使用了多块读
SQL> select 94*16 from dual;
1504
SQL> select event, total_waits
2 from v$session_event
3 where sid = 822
4 and wait_class = 'User I/O'
5 order by 1;
db file scattered read 189 db file sequential read 633
==〉db file scattered read:94,说明使用了多块读
3,使用并行提示,全表扫描缓存到buffer cache还是pga?是否使用多块读?
==> 读入pga;使用了多块读。
SQL> alter system flush shared_pool;
System altered
SQL> alter system flush buffer_cache;
System altered
SQL> select status, count(*) from v$bh where bjd = 155073 group by status;
free 1232
SQL>
SQL> select statistic_name,value
2 from v$segment_statistics ss
3 where wner = user
4 and object_name = 'T'
5 and value>0
6 order by 2;
segment scans 1
db block changes 256
physical writes direct 1125
physical writes 1151
physical reads 3388
logical reads 7376
space used 9216000
space allocated 9437184
8 rows selected
SQL> select sid, name, value
2 from v$mystat ses, v$statname sn
3 where ses.STATISTIC# = sn.STATISTIC#
4 and value > 0
5 and name like '%read%'
6 order by 3;
822 physical read total multi block requests 272
822 physical read total IO requests 1546
822 physical read IO requests 1546
822 physical reads cache prefetch 3094
822 physical reads 4640
822 physical reads cache 4640
822 no work - consistent read gets 671268
822 session logical reads 1153284
822 physical read total bytes 38010880
822 physical read bytes 38010880
10 rows selected
SQL> select event, total_waits
2 from v$session_event
3 where sid = 822
4 and wait_class = 'User I/O'
5 order by 1;
db file scattered read 272
db file sequential read 1278
SQL> select /*+ parallel(t 8) */ count(*) from t;
80677
SQL> select sql_id,disk_reads,direct_writes,user_io_wait_time,buffer_gets,sql_text from v$sql where sql_text like '%count(*) from t%';
6861j0dxkvvr4 1136 0 1056 1388 select /*+ parallel(t 8) */ count(*) from t
SQL> select * from table(dbms_xplan.display_cursor('6861j0dxkvvr4'));
SQL_ID 6861j0dxkvvr4, child number 0
select /*+ parallel(t 8) */ count(*) from t
NOTE: cannot fetch plan for SQL_ID: 6861j0dxkvvr4, CHILD_NUMBER: 0
Please verify value of SQL_ID and CHILD_NUMBER;
It could also be that the plan is no longer in cursor cache (check v$sql_p
8 rows selected
SQL> explain plan for select /*+ parallel(t 8) */ count(*) from t
2 ;
Explained
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 3126468333
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time | T
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 13 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | PX COORDINATOR | | | | |
| 3 | PX SEND QC (RANDOM) | :TQ10000 | 1 | | | Q1,
| 4 | SORT AGGREGATE | | 1 | | | Q1,
| 5 | PX BLOCK ITERATOR | | 80677 | 13 (0)| 00:00:01 | Q1,
| 6 | TABLE ACCESS FULL| T | 80677 | 13 (0)| 00:00:01 | Q1,
--------------------------------------------------------------------------------
13 rows selected
SQL> select status, count(*) from v$bh where bjd = 155073 group by status;
xcur 1
free 720
==〉xcur:1,说明缓存到了pga
SQL>
SQL> select statistic_name,value
2 from v$segment_statistics ss
3 where wner = user
4 and object_name = 'T'
5 and value>0
6 order by 2;
segment scans 108
db block changes 256
physical reads direct 1125 physical writes direct 1125
physical writes 1151
physical reads 4514 logical reads 8720
space used 9216000
space allocated 9437184
==〉physical reads direct:1125,说明使用了直接读
SQL> select sid, name, value
2 from v$mystat ses, v$statname sn
3 where ses.STATISTIC# = sn.STATISTIC#
4 and value > 0
5 and name like '%read%'
6 order by 3;
822 table scans (direct read) 107 822 physical read total multi block requests 384 822 physical reads direct 1125 822 physical read total IO requests 1733 822 physical read IO requests 1733 822 physical reads cache prefetch 3094
822 physical reads cache 4714
822 physical reads 5839 822 no work - consistent read gets 678775
822 session logical reads 1167932
822 physical read total bytes 47833088
822 physical read bytes 47833088
==〉physical read total multi block requests:112,说明使用了多块读
SQL> select event, total_waits
2 from v$session_event
3 where sid = 822
4 and wait_class = 'User I/O'
5 order by 1;
db file scattered read 272
db file sequential read 1348
==〉db file scattered read:0,说明没有使用多块读或这种情况下的多块读不计入该事件计数。
4,遗留问题:
表上的cache属性,可以控制在全表扫描时把数据放置在LRU的热端。为了缓存大表,该属性是否影响缓存效果?
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/18922393/viewspace-754214/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/18922393/viewspace-754214/