[English]
作者:
fuyuncat
来源:
www.HelloDBA.com
我们知道,参数"_small_table_threshold"决定了一个表是否是小表。对于大表而言,在LRU算法中,从其读取的数据块会被放置在LRU链表上不同于小表数据块的位置;而在执行一些大数据量的操作时,如并行查询、直接载入等,大表的数据块是绕过缓存直接从磁盘读取的。
默认情况下,Oracle在启动实例时,自动设置"_small_table_threshold"为"_db_block_buffers"的2%。例如,在我本机的DB(10.2.0.4)上,
SQL代码
- HELLODBA.COM>select name, value from all_parameters where name = '_db_block_buffers';
- NAME VALUE
- ------------------------------ ------------------------------
- _db_block_buffers 15918
- HELLODBA.COM>select name, value from all_parameters where name = '_small_table_threshold';
- NAME VALUE
- ------------------------------ ------------------------------
- _small_table_threshold 318
"_db_block_buffers"是15918,因此,"_small_table_threshold"=15918*0.02=318。
为了演示它是如何其作用的,我们对一张测试表进行并行查询操作:
SQL代码
- HELLODBA.COM>create table dummy_tab as select a.* from dba_tables a, dba_tables b where rownum<=10650;
- Table created.
- HELLODBA.COM>exec dba_seg_info('DEMO','TABLE','DUMMY_TAB');
- Free Blocks.............................
- Total Blocks............................384
- Total Bytes.............................3145728
- Unused Blocks...........................52
- Unused Bytes............................425984
- Last Used Ext FileId....................5
- Last Used Ext BlockId...................265097
- Last Used Block.........................76
- *************************************************
- The segment is analyzed
- 0% -- 25% free space blocks.............0
- 0% -- 25% free space bytes..............0
- 25% -- 50% free space blocks............0
- 25% -- 50% free space bytes.............0
- 50% -- 75% free space blocks............0
- 50% -- 75% free space bytes.............0
- 75% -- 100% free space blocks...........0
- 75% -- 100% free space bytes............0
- Unused Blocks...........................0
- Unused Bytes............................0
- Total Blocks............................318
- Total bytes.............................2605056
- PL/SQL procedure successfully completed.
在这里,我们建立了一张测试表,并且我刻意让其数据块数正好等于临界值。然后对其进行并行查询:
SQL代码
- HELLODBA.COM>set autot trace
- HELLODBA.COM>select /*+parallel(t 2)*/* from dummy_tab t;
- 10650 rows selected.
- Execution Plan
- ----------------------------------------------------------
- Plan hash value: 2889160364
- ---------------------------------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | TQ |IN-OUT| PQ Distrib |
- ---------------------------------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 12237 | 5963K| 372 (1)| 00:00:02 | | | |
- | 1 | PX COORDINATOR | | | | | | | | |
- | 2 | PX SEND QC (RANDOM)| :TQ10000 | 12237 | 5963K| 372 (1)| 00:00:02 | Q1,00 | P->S | QC (RAND) |
- | 3 | PX BLOCK ITERATOR | | 12237 | 5963K| 372 (1)| 00:00:02 | Q1,00 | PCWC | |
- | 4 | TABLE ACCESS FULL| DUMMY_TAB | 12237 | 5963K| 372 (1)| 00:00:02 | Q1,00 | PCWP | |
- ---------------------------------------------------------------------------------------------------------------
- Note
- -----
- - dynamic sampling used for this statement
- Statistics
- ----------------------------------------------------------
- 1587 recursive calls
- 3 db block gets
- 718 consistent gets
- 318 physical reads
- 780 redo size
- 254481 bytes sent via SQL*Net to client
- 8291 bytes received via SQL*Net from client
- 711 SQL*Net roundtrips to/from client
- 7 sorts (memory)
- 0 sorts (disk)
- 10650 rows processed
- HELLODBA.COM>select /*+parallel(t 2)*/* from dummy_tab t;
- 10650 rows selected.
- Execution Plan
- ----------------------------------------------------------
- Plan hash value: 2889160364
- ---------------------------------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | TQ |IN-OUT| PQ Distrib |
- ---------------------------------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 12237 | 5963K| 372 (1)| 00:00:02 | | | |
- | 1 | PX COORDINATOR | | | | | | | | |
- | 2 | PX SEND QC (RANDOM)| :TQ10000 | 12237 | 5963K| 372 (1)| 00:00:02 | Q1,00 | P->S | QC (RAND) |
- | 3 | PX BLOCK ITERATOR | | 12237 | 5963K| 372 (1)| 00:00:02 | Q1,00 | PCWC | |
- | 4 | TABLE ACCESS FULL| DUMMY_TAB | 12237 | 5963K| 372 (1)| 00:00:02 | Q1,00 | PCWP | |
- ---------------------------------------------------------------------------------------------------------------
- Note
- -----
- - dynamic sampling used for this statement
- Statistics
- ----------------------------------------------------------
- 6 recursive calls
- 0 db block gets
- 421 consistent gets
- 0 physical reads
- 0 redo size
- 256926 bytes sent via SQL*Net to client
- 8291 bytes received via SQL*Net from client
- 711 SQL*Net roundtrips to/from client
- 1 sorts (memory)
- 0 sorts (disk)
- 10650 rows processed
可以看到,在第二次运行时,已经没有physical reads了。这说明在第一次运行时,数据块被缓存到buffer cache,并且第二次运行就从buffer cache中读取了数据。也就是说,此时它是一张“小表”。
现在,我们插入少量数据抬高其水位:
SQL代码
- HELLODBA.COM>insert /*+append*/into dummy_tab select * from t_tables where rownum<=30;
- 30 rows created.
- HELLODBA.COM>commit;
- Commit complete.
- HELLODBA.COM>exec dba_seg_info('DEMO','TABLE','DUMMY_TAB');
- Free Blocks.............................
- Total Blocks............................384
- Total Bytes.............................3145728
- Unused Blocks...........................51
- Unused Bytes............................417792
- Last Used Ext FileId....................5
- Last Used Ext BlockId...................265481
- Last Used Block.........................77
- *************************************************
- The segment is analyzed
- 0% -- 25% free space blocks.............0
- 0% -- 25% free space bytes..............0
- 25% -- 50% free space blocks............0
- 25% -- 50% free space bytes.............0
- 50% -- 75% free space blocks............0
- 50% -- 75% free space bytes.............0
- 75% -- 100% free space blocks...........0
- 75% -- 100% free space bytes............0
- Unused Blocks...........................0
- Unused Bytes............................0
- Total Blocks............................319
- Total bytes.............................2613248
- PL/SQL procedure successfully completed.
可以看到,增加了一个数据块,刚刚过了临界值。然后我们再运行并行查询,
SQL代码
- HELLODBA.COM>set autot trace statistics
- HELLODBA.COM>select /*+parallel(t 2)*/* from dummy_tab t;
- 10680 rows selected.
- Statistics
- ----------------------------------------------------------
- 6 recursive calls
- 0 db block gets
- 373 consistent gets
- 319 physical reads
- 0 redo size
- 259280 bytes sent via SQL*Net to client
- 8313 bytes received via SQL*Net from client
- 713 SQL*Net roundtrips to/from client
- 1 sorts (memory)
- 0 sorts (disk)
- 10680 rows processed
- HELLODBA.COM>select /*+parallel(t 2)*/* from dummy_tab t;
- 10680 rows selected.
- Statistics
- ----------------------------------------------------------
- 6 recursive calls
- 0 db block gets
- 373 consistent gets
- 319 physical reads
- 0 redo size
- 256259 bytes sent via SQL*Net to client
- 8313 bytes received via SQL*Net from client
- 713 SQL*Net roundtrips to/from client
- 1 sorts (memory)
- 0 sorts (disk)
- 10680 rows processed
可以发现physical reads再也不消失了。这说明数据块始终是绕过了buffer cache,直接从磁盘读取的。统计数据"Physical Reads Direct"更加直观的说明了这一行为:
SQL代码
- D:\HelloDBA.COM\perl scripts>perl getsqlstats.pl
- tnsname (default is orcl):
- user name (default is demo):
- password:
- Array size (Default is 32):
- Execution plan format (Default is TYPICAL):
- SQL to be executed (without ;):
- select /*+parallel(t 2)*/* from dummy_tab t
- Seesion ID: 299 Process ID: 101596
- SQL Prepared. Process paused, press ENTER to continue...
- SQL is executing ...
- SQL Executed. Process Paused, press ENTER to continue...
- SQL_ID 9fjrktd5gkmmh, child number 0
- -------------------------------------
- select /*+parallel(t 2)*/* from dummy_tab t
- Plan hash value: 2889160364
- ---------------------------------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | TQ |IN-OUT| PQ Distrib |
- ---------------------------------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | | | 372 (100)| | | | |
- | 1 | PX COORDINATOR | | | | | | | | |
- | 2 | PX SEND QC (RANDOM)| :TQ10000 | 12237 | 5963K| 372 (1)| 00:00:02 | Q1,00 | P->S | QC (RAND) |
- | 3 | PX BLOCK ITERATOR | | 12237 | 5963K| 372 (1)| 00:00:02 | Q1,00 | PCWC | |
- |* 4 | TABLE ACCESS FULL| DUMMY_TAB | 12237 | 5963K| 372 (1)| 00:00:02 | Q1,00 | PCWP | |
- ---------------------------------------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 4 - access(:Z>=:Z AND :Z<=:Z)
- Note
- -----
- - dynamic sampling used for this statement
- statistics
- -----------------------------------------
- consistent changes: 0
- consistent gets: 373
- consistent gets direct: 319
- consistent gets from cache: 54
- db block changes: 0
- db block gets: 0
- db block gets direct: 0
- db block gets from cache: 0
- physical reads: 319
- physical reads cache: 0
- physical reads direct: 319
- physical reads direct temporary tablespace: 0
- session logical reads: 373
这里还有一个我们需要知道的信息是,这里有6个递归调用用于并行查询,并且它们产生了相应的CR。而通过10046事件,我们可以看到实际上并行查询语句本身只产生了3次CR,读取段头,以获取其数据块数。
--- Fuyuncat ---
上一篇:Oracle的排序算法 | 下一篇:Oracle 11g 直接IO自动调节 |
本类中的所有文章 |