Oracle中ASSM模式下,全表掃描的L3塊的邏輯讀的影響

PiscesCanon發表於2017-06-15
前言:
本問題由之前的實驗擴充遺留的一些疑問,詳見:http://blog.itpub.net/30174570/viewspace-2140241/
排除db_file_multiblock_read_count引數和動態取樣(詳見:http://blog.itpub.net/30174570/viewspace-2140240/)的影響。

作業系統環境:
  1. [oracle@oracle ~]$ uname -a
  2. Linux oracle.example.com 2.6.32-431.el6.x86_64 #1 SMP Sun Nov 10 22:19:54 EST 2013 x86_64 x86_64 x86_64 GNU/Linux
  3. [oracle@oracle ~]$ lsb_release -a
  4. LSB Version:     :base-4.0-amd64:base-4.0-noarch:core-4.0-amd64:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0-noarch:printing-4.0-amd64:printing-4.0-noarch
  5. Distributor ID:  RedHatEnterpriseServer
  6. Description:     Red Hat Enterprise Linux Server release 6.5 (Santiago)
  7. Release:         6.5
  8. Codename:        Santiago

資料庫版本:
  1. SYS@proc> select * from v$version where rownum=1;

  2. BANNER
  3. --------------------------------------------------------------------------------
  4. Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

構造測試資料:
  1. SYS@proc> drop table t purge;

  2. Table dropped.

  3. SYS@proc> create table t as select * from dba_objects where rownum<=1200;

  4. Table created.

  5. SYS@proc> alter table t move tablespace test;

  6. Table altered.

  7. SYS@proc> select dbms_rowid.rowid_block_number(rowid) block#,min(rownum),max(rownum) from t group by dbms_rowid.rowid_block_number(rowid) order by dbms_rowid.rowid_block_number(rowid);

  8.     BLOCK# MIN(ROWNUM) MAX(ROWNUM)
  9. ---------- ----------- -----------
  10.        131           1          88
  11.        132          89         171
  12.        133         172         251
  13.        134         252         329
  14.        135         330         407
  15.        136         408         487
  16.        137         488         567
  17.        138         568         646
  18.        139         647         724
  19.        140         725         798
  20.        141         799         873

  21.     BLOCK# MIN(ROWNUM) MAX(ROWNUM)
  22. ---------- ----------- -----------
  23.        142         874         946
  24.        143         947        1022
  25.        145        1023        1104
  26.        146        1105        1179
  27.        147        1180        1200

  28. 16 rows selected.

  29. SYS@proc> select EXTENT_ID,FILE_ID,BLOCK_ID,BLOCKS from dba_extents where owner='SYS' and SEGMENT_NAME='T';

  30.  EXTENT_ID    FILE_ID   BLOCK_ID     BLOCKS
  31. ---------- ---------- ---------- ----------
  32.          0          6        128          8    --128 129 130 131 132 133 134 135
  33.          1          6        136          8
  34.          2          6        144          8

引出問題:
  1. SYS@proc> alter system set db_file_multiblock_read_count=1; --避免該引數的影響

  2. System altered.

  3. SYS@proc> show parameter db_file_multiblock_read_count

  4. NAME                                 TYPE        VALUE
  5. ------------------------------------ ----------- ------------------------------
  6. db_file_multiblock_read_count        integer     1

  7. SYS@proc> analyze table t compute statistics;   --避免動態取樣的影響

  8. Table analyzed.

  9. SYS@proc> alter system flush buffer_cache;

  10. System altered.

  11. SYS@proc> select file#,dbablk,state from x$bh where obj=(select data_object_id from dba_objects where owner='SYS' and object_name='T') and state<>0 order by dbablk;

  12. no rows selected

  13. SYS@proc> select count(*) from t where rownum<=171;

  14.   COUNT(*)
  15. ----------
  16.        171

  17. SYS@proc> select file#,dbablk,state from x$bh where obj=(select data_object_id from dba_objects where owner='SYS' and object_name='T') and state<>0 order by dbablk;

  18.      FILE# DBABLK     STATE
  19. ---------- ---------- ----------
  20.      6     130     1
  21.      6     131     1
  22.      6     132     1
sql語句"select count(*) from t where rownum<=171"只讀取了131,132兩個塊,但是130也被讀取進去,這裡讀取該塊的作用是什麼?

實驗過程:
  1. SYS@proc> alter system flush buffer_cache;

  2. System altered.

  3. SYS@proc> select file#,dbablk,state from x$bh where obj=(select data_object_id from dba_objects where owner='SYS' and object_name='T') and state<>0 order by dbablk;

  4. no rows selected

  5. SYS@proc> select HEADER_FILE,HEADER_BLOCK from dba_segments where owner='SYS' and segment_name='T';   --該語句可確定段頭塊是130

  6. HEADER_FILE HEADER_BLOCK
  7. ----------- ------------
  8.           6          130

  9. SYS@proc> select file#,dbablk,state from x$bh where obj=(select data_object_id from dba_objects where owner='SYS' and object_name='T') and state<>0 order by dbablk;

  10. no rows selected

  11. SYS@proc> select count(*) from t where rownum<=171;

  12.   COUNT(*)
  13. ----------
  14.        171

  15. SYS@proc> set autotrace on
  16. SYS@proc> select count(*) from t where rownum<=171;

  17.   COUNT(*)
  18. ----------
  19.        171


  20. Execution Plan
  21. ----------------------------------------------------------
  22. Plan hash value: 239743108

  23. --------------------------------------------------------------------
  24. | Id  | Operation           | Name | Rows  | Cost (%CPU)| Time     |
  25. --------------------------------------------------------------------
  26. |   0 | SELECT STATEMENT    |      |     1 |    21   (0)| 00:00:01 |
  27. |   1 |  SORT AGGREGATE     |      |     1 |            |          |
  28. |*  2 |   COUNT STOPKEY     |      |       |            |          |
  29. |   3 |    TABLE ACCESS FULL| T    |  1200 |    21   (0)| 00:00:01 |
  30. --------------------------------------------------------------------

  31. Predicate Information (identified by operation id):
  32. ---------------------------------------------------

  33.    2 - filter(ROWNUM<=171)


  34. Statistics
  35. ----------------------------------------------------------
  36.      0 recursive calls
  37.      0 db block gets
  38.      4 consistent gets
  39.      0 physical reads
  40.      0 redo size
  41.    527 bytes sent via SQL*Net to client
  42.    523 bytes received via SQL*Net from client
  43.      2 SQL*Net roundtrips to/from client
  44.      0 sorts (memory)
  45.      0 sorts (disk)
  46.      1 rows processed

  47. SYS@proc> set autotrace off
  48. SYS@proc> select file#,dbablk,state from x$bh where obj=(select data_object_id from dba_objects where owner='SYS' and object_name='T') and state<>0 order by dbablk;

  49.      FILE#     DBABLK      STATE
  50. ---------- ---------- ----------
  51.          6        130          1
  52.          6        131          1
  53.          6        132          1
上述實驗過程第9行處,得出段頭塊是130號塊,在ASSM中,段頭是第一個L3塊。
為什麼該處的邏輯讀是4呢?全表掃描下,會跳過L1(塊128)和L2(塊129),直接讀取段頭L3和高水位線以下的所有塊(為什麼全表掃描只讀了131和132,受到rownum的影響,詳情見http://blog.itpub.net/30174570/viewspace-2140240/)。但是L3要讀取兩次,所以邏輯讀為4。讀取L3兩次,一次讀取Extent Map,一次讀取Auxillary Map。

回到一開始的問題,Oracle通過讀取L3段頭塊確定全表掃描應該讀取的區和區中的資料塊,這個就是為什麼除了131和132這兩個實際包含資料的資料塊以外,還要讀取130塊的原因。

資料塊130的部分dump資訊:
  1. Extent Control Header
  2.   -----------------------------------------------------------------
  3.   Extent Header:: spare1: 0 spare2: 0 #extents: 3 #blocks: 24
  4.                   last map 0x00000000 #maps: 0 offset: 2716
  5.       Highwater:: 0x01800094 ext#: 2 blk#: 4 ext size: 8
  6.   #blocks in seg. hdr's freelists: 0
  7.   #blocks below: 20
  8.   mapblk 0x00000000 offset: 2
  9.                    Unlocked
  10.   --------------------------------------------------------
  11.   Low HighWater Mark :
  12.       Highwater:: 0x01800094 ext#: 2 blk#: 4 ext size: 8
  13.   #blocks in seg. hdr's freelists: 0
  14.   #blocks below: 20
  15.   mapblk 0x00000000 offset: 2
  16.   Level 1 BMB for High HWM block: 0x01800090
  17.   Level 1 BMB for Low HWM block: 0x01800090
  18.   --------------------------------------------------------
  19.   Segment Type: 1 nl2: 1 blksz: 8192 fbsz: 0
  20.   L2 Array start offset: 0x00001434
  21.   First Level 3 BMB: 0x00000000
  22.   L2 Hint for inserts: 0x01800081
  23.   Last Level 1 BMB: 0x01800090
  24.   Last Level II BMB: 0x01800081
  25.   Last Level III BMB: 0x00000000
  26.      Map Header:: next 0x00000000 #extents: 3 obj#: 89405 flag: 0x10000000
  27.   Inc # 0
  28.   Extent Map
  29.   -----------------------------------------------------------------
  30.    0x01800080 length: 8
  31.    0x01800088 length: 8
  32.    0x01800090 length: 8

  33.   Auxillary Map
  34.   --------------------------------------------------------
  35.    Extent 0 : L1 dba: 0x01800080 Data dba: 0x01800083           "0x01800083"->二進位制:00000001 10000000 00000000 10000011
  36.    Extent 1 : L1 dba: 0x01800080 Data dba: 0x01800088            前10位是檔案號,後22位是塊號,0000000110->檔案號:6,000000 00000000 10000011->資料塊:131
  37.    Extent 2 : L1 dba: 0x01800090 Data dba: 0x01800091
  38.   --------------------------------------------------------

  39.    Second Level Bitmap block DBAs
  40.    --------------------------------------------------------
  41.    DBA 1: 0x01800081

  42. End dump data blocks tsn: 9 file#: 6 minblk 130 maxblk 130

  1. SYS@proc> select to_number('01800083','xxxxxxxx') from dual;

  2. TO_NUMBER('01800083','XXXXXXXX')
  3. --------------------------------
  4.                         25165955

  5. SYS@proc> select dbms_utility.data_block_address_file(25165955) from dual;

  6. DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(25165955)
  7. ----------------------------------------------
  8.                                              6

  9. SYS@proc> select dbms_utility.data_block_address_block(25165955) from dual;

  10. DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(25165955)
  11. -----------------------------------------------
  12.                                             131

其他擴充:
  1. SYS@proc> --16進位制數0x01800080轉換為10進位制數
  2. SYS@proc> select to_number('01800080','xxxxxxxx') from dual;

  3. TO_NUMBER('01800080','XXXXXXXX')
  4. --------------------------------
  5.                         25165952

  6. SYS@proc> --10進位制25165952轉換為16進位制
  7. SYS@proc> select to_char(25165952,'xxxxxxxx') from dual;

  8. TO_CHAR(2
  9. ---------
  10.   1800080

  11. SYS@proc> --2進位制轉換為10進位制
  12. SYS@proc> select bin_to_num(1,1,0,1) a,bin_to_num(1,0) b from dual;

  13.          A          B
  14. ---------- ----------
  15.         13          2

  16. SYS@proc> select bin_to_num(1,1,1,0,1) from dual;

  17. BIN_TO_NUM(1,1,1,0,1)
  18. ---------------------
  19.                    29


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30174570/viewspace-2140813/,如需轉載,請註明出處,否則將追究法律責任。

相關文章