高水位线和全表扫描

 高水位线好比水库中储水的水位线,用于描述数据库中段的扩展方式。高水位线对全表扫描方式有着至关重要的影响。当使用delete 操作
表记录时,高水位线并不会下降,随之导致的是全表扫描的实际开销并没有任何减少。本文给出高水位线的描述,如何降低高水位线,以及高水
位线对全表扫描的影响。

 

一、何谓高水位线
    如前所述,类似于水库中储水的水位线。只不过在数据库中用于描述段的扩展方式。
    可以将数据段或索引段等想象为一个从左到右依次排开的一系列块。当这些块中未填充任何数据时,高水位线位于块的最左端(底端)
    随着记录的不断增加,新块不断地被填充并使用,高水位线随之向右移动。高水位线之上为未格式化的数据块。
    删除(delete)操作之后,高水位线之下的块处于空闲状态,但高水位线并不随之下降,直到重建,截断或收缩表段。
    全表扫描会扫描高水位线之下的所有块,包括空闲数据块(执行了delete操作)。
    
    低高水位线
      是在使用ASSM时的一个概念。即使用ASSM时除了高水位线之外,还包括一个低高水位线。低高水位线一定是位于高水位线之下。
      当段使用MSSM管理方式时只有一种情况即只存在一个高水位线。
      使用MMSM时,当HWM升高时,Oracle立即格式化所有块且有效,并可以安全读取。仅当第一次使用时完成格式化,便于安全读取数据。
      使用ASSM时,当HWM升高时,Oracle并不会立即格式化所有块。仅当第一次使用时完成格式化,便于安全读取数据。
      使用低高水位线可以减少当全面扫描表段时,低高水位线与高水位线之间不安全块的检查数量。即低高水位线之下的块不再检查。
   
二、演示高水位线与全表扫描

[sql] view plain copy print ?
  1. SQL> create table t    -->创建测试表   
  2.   2  as  
  3.   3  select rownum as id,  
  4.   4  round(dbms_random.normal*1000) AS val1,  
  5.   5  dbms_random.string('p',250) AS pad  
  6.   6  from dual  
  7.   7  connect by level <=10000;  
  8.   
  9. Table created.  
  10.   
  11. SQL> exec dbms_stats.gather_table_stats('SCOTT','T',cascade=>true);  -->收集统计信息   
  12.   
  13. SQL> @Tab_Stat                        -->从dba_tab_statistics中获得表对象的统计信息,此时无empty_blocks的信息   
  14. Enter value for input_table_name: t  
  15. Enter value for input_owner: scott  
  16.   
  17.   NUM_ROWS       BLKS    EM_BLKS  AVG_SPACE  CHAIN_CNT AVG_ROW_LEN AVG_ROWS_PER_BLOCK LST_ANLY  STA  
  18. ---------- ---------- ---------- ---------- ---------- ----------- ------------------ --------- ---   
  19.      10000        387          0          0          0         259                 26 03-NOV-11 NO  
  20.   
  21. /**************************************************/  
  22. /* Author: Robinson Cheng                         */   
  23. /* Blog:   http://blog.csdn.net/robinson_0612     */  
  24. /* MSN:    [email protected]              */  
  25. /* QQ:     645746311                              */   
  26. /**************************************************/   
  27.   
  28. SQL> analyze table t compute statistics;    -->执行analyze   
  29.   
  30. SQL> @Tab_Stat                              -->此时的empty_blocks值为125   
  31. Enter value for input_table_name: t  
  32. Enter value for input_owner: scott  
  33.   
  34.   NUM_ROWS       BLKS    EM_BLKS  AVG_SPACE  CHAIN_CNT AVG_ROW_LEN AVG_ROWS_PER_BLOCK LST_ANLY  STA  
  35. ---------- ---------- ---------- ---------- ---------- ----------- ------------------ --------- ---   
  36.      10000        387        125        920          0         262                 26 03-NOV-11 NO  
  37.   
  38. SQL> col segment_name format a15  
  39. SQL> select segment_name,segment_type,blocks,extents from dba_segments  -->查看表段上的块的信息   
  40.   2  where segment_name='T' and owner='SCOTT';  
  41.   
  42. SEGMENT_NAME    SEGMENT_TYPE           BLOCKS    EXTENTS            -->此数据字典中记录的块数为512块(包含了已使用块与空闲块)   
  43. --------------- ------------------ ---------- ----------   
  44. T               TABLE                     512         19  
  45.   
  46. SQL> set autotrace traceonly;    -->开启autotrace   
  47. SQL> select count(*) from t;     -->此时SQL语句的执行计划为全表扫描(执行计划中部分信息被省略)   
  48.   
  49. Execution Plan  
  50. ----------------------------------------------------------   
  51. Plan hash value: 2966233522  
  52.   
  53. -------------------------------------------------------------------   
  54. | Id  | Operation          | Name | Rows  | Cost (%CPU)| Time     |  
  55. -------------------------------------------------------------------   
  56. |   0 | SELECT STATEMENT   |      |     1 |    86   (0)| 00:00:02 |  
  57. |   1 |  SORT AGGREGATE    |      |     1 |            |          |  
  58. |   2 |   TABLE ACCESS FULL| T    | 10000 |    86   (0)| 00:00:02 |  
  59. -------------------------------------------------------------------   
  60.   
  61. Statistics  
  62. ----------------------------------------------------------   
  63.           1  recursive calls  
  64.           0  db block gets  
  65.         375  consistent gets          -->consistent gets的值为375   
  66.           0  physical reads  
  67.   
  68. SQL> set autotrace off;  
  69. SQL> delete from t where rownum<=9900;   -->删除大多数的记录,删除后剩余记录值为100   
  70.   
  71. 9900 rows deleted.  
  72. SQL> commit;  
  73.   
  74. SQL> exec dbms_stats.gather_table_stats('SCOTT','T',cascade=>true); -->收集统计信息   
  75.   
  76. SQL> analyze table t compute statistics;  -->收集统计信息   
  77.   
  78. SQL> @Tab_Stat                           -->此时对象上的统计信息无任何变化,即高水位线没有发生任何变化   
  79. Enter value for input_table_name: t  
  80. Enter value for input_owner: scott  
  81.   
  82.   NUM_ROWS       BLKS    EM_BLKS  AVG_SPACE  CHAIN_CNT AVG_ROW_LEN AVG_ROWS_PER_BLOCK LST_ANLY  STA  
  83. ---------- ---------- ---------- ---------- ---------- ----------- ------------------ --------- ---   
  84.        100        387        125       7921          0         262                  0 03-NOV-11 NO  
  85.                    
  86. SQL> set autotrace traceonly      
  87. SQL> select count(*) from t;     -->SQL的执行计划中预估的值准确,为100行   
  88.   
  89. Execution Plan  
  90. ----------------------------------------------------------   
  91. Plan hash value: 2966233522  
  92.   
  93. -------------------------------------------------------------------   
  94. | Id  | Operation          | Name | Rows  | Cost (%CPU)| Time     |  
  95. -------------------------------------------------------------------   
  96. |   0 | SELECT STATEMENT   |      |     1 |    86   (0)| 00:00:02 |  
  97. |   1 |  SORT AGGREGATE    |      |     1 |            |          |  
  98. |   2 |   TABLE ACCESS FULL| T    |   100 |    86   (0)| 00:00:02 |  
  99. -------------------------------------------------------------------   
  100.   
  101. Statistics  
  102. ----------------------------------------------------------   
  103.           1  recursive calls  
  104.           0  db block gets  
  105.         375  consistent gets   -->consistent gets的值仍然为375,并没有下降   
  106.           0  physical reads  
  107.   
  108. SQL> set autotrace off;  
  109. SQL> alter table t enable row movement;      -->启用row movement   
  110.   
  111. SQL> alter table t shrink space cascade;     --> 实施shrink space   
  112.   
  113. SQL> alter table t disable row movement;  
  114.   
  115. SQL> exec dbms_stats.gather_table_stats('SCOTT','T');  
  116.   
  117. SQL> analyze table t compute statistics;  
  118.   
  119. SQL> @Tab_Stat                           -->此时对象上的统计信息已发生变化,已使用的块为4块,空闲块为4块   
  120. Enter value for input_table_name: t  
  121. Enter value for input_owner: scott  
  122.   NUM_ROWS       BLKS    EM_BLKS  AVG_SPACE  CHAIN_CNT AVG_ROW_LEN AVG_ROWS_PER_BLOCK LST_ANLY  STA  
  123. ---------- ---------- ---------- ---------- ---------- ----------- ------------------ --------- ---   
  124.        100          4          4       7921          0         259                 25 03-NOV-11 NO  
  125.   
  126. SQL> set autotrace traceonly   
  127. SQL> select count(*) from t;  
  128.   
  129. Execution Plan  
  130. ----------------------------------------------------------   
  131. Plan hash value: 2966233522  
  132.   
  133. -------------------------------------------------------------------   
  134. | Id  | Operation          | Name | Rows  | Cost (%CPU)| Time     |  
  135. -------------------------------------------------------------------   
  136. |   0 | SELECT STATEMENT   |      |     1 |     3   (0)| 00:00:01 |  
  137. |   1 |  SORT AGGREGATE    |      |     1 |            |          |  
  138. |   2 |   TABLE ACCESS FULL| T    |   100 |     3   (0)| 00:00:01 |  
  139. -------------------------------------------------------------------   
  140.   
  141. Statistics  
  142. ----------------------------------------------------------   
  143.           1  recursive calls  
  144.           0  db block gets  
  145.           6  consistent gets    -->表段收缩之后,consistent gets由375下降为6   
  146.           0  physical reads  
  147.                    
  148. SQL> truncate table t;  -->使用表截断技术(turncate table)   
  149.   
  150. Table truncated.  
  151.   
  152. SQL> exec dbms_stats.gather_table_stats('SCOTT','T');  -->收集统计信息   
  153.   
  154. PL/SQL procedure successfully completed.  
  155.   
  156. SQL> select count(*) from t;   -->此时执行计划中的rows变为1   
  157.   
  158. Execution Plan  
  159. ----------------------------------------------------------   
  160. Plan hash value: 2966233522  
  161.   
  162. -------------------------------------------------------------------   
  163. | Id  | Operation          | Name | Rows  | Cost (%CPU)| Time     |  
  164. -------------------------------------------------------------------   
  165. |   0 | SELECT STATEMENT   |      |     1 |     2   (0)| 00:00:01 |  
  166. |   1 |  SORT AGGREGATE    |      |     1 |            |          |  
  167. |   2 |   TABLE ACCESS FULL| T    |     1 |     2   (0)| 00:00:01 |  
  168. -------------------------------------------------------------------   
  169.   
  170. Statistics  
  171. ----------------------------------------------------------   
  172.           1  recursive calls  
  173.           0  db block gets  
  174.           3  consistent gets   -->consistent gets的值降为3   
  175.           0  physical reads  
SQL> create table t -->创建测试表 2 as 3 select rownum as id, 4 round(dbms_random.normal*1000) AS val1, 5 dbms_random.string('p',250) AS pad 6 from dual 7 connect by level <=10000; Table created. SQL> exec dbms_stats.gather_table_stats('SCOTT','T',cascade=>true); -->收集统计信息 SQL> @Tab_Stat -->从dba_tab_statistics中获得表对象的统计信息,此时无empty_blocks的信息 Enter value for input_table_name: t Enter value for input_owner: scott NUM_ROWS BLKS EM_BLKS AVG_SPACE CHAIN_CNT AVG_ROW_LEN AVG_ROWS_PER_BLOCK LST_ANLY STA ---------- ---------- ---------- ---------- ---------- ----------- ------------------ --------- --- 10000 387 0 0 0 259 26 03-NOV-11 NO /**************************************************/ /* Author: Robinson Cheng */ /* Blog: http://blog.csdn.net/robinson_0612 */ /* MSN: [email protected] */ /* QQ: 645746311 */ /**************************************************/ SQL> analyze table t compute statistics; -->执行analyze SQL> @Tab_Stat -->此时的empty_blocks值为125 Enter value for input_table_name: t Enter value for input_owner: scott NUM_ROWS BLKS EM_BLKS AVG_SPACE CHAIN_CNT AVG_ROW_LEN AVG_ROWS_PER_BLOCK LST_ANLY STA ---------- ---------- ---------- ---------- ---------- ----------- ------------------ --------- --- 10000 387 125 920 0 262 26 03-NOV-11 NO SQL> col segment_name format a15 SQL> select segment_name,segment_type,blocks,extents from dba_segments -->查看表段上的块的信息 2 where segment_name='T' and owner='SCOTT'; SEGMENT_NAME SEGMENT_TYPE BLOCKS EXTENTS -->此数据字典中记录的块数为512块(包含了已使用块与空闲块) --------------- ------------------ ---------- ---------- T TABLE 512 19 SQL> set autotrace traceonly; -->开启autotrace SQL> select count(*) from t; -->此时SQL语句的执行计划为全表扫描(执行计划中部分信息被省略) Execution Plan ---------------------------------------------------------- Plan hash value: 2966233522 ------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | ------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 86 (0)| 00:00:02 | | 1 | SORT AGGREGATE | | 1 | | | | 2 | TABLE ACCESS FULL| T | 10000 | 86 (0)| 00:00:02 | ------------------------------------------------------------------- Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 375 consistent gets -->consistent gets的值为375 0 physical reads SQL> set autotrace off; SQL> delete from t where rownum<=9900; -->删除大多数的记录,删除后剩余记录值为100 9900 rows deleted. SQL> commit; SQL> exec dbms_stats.gather_table_stats('SCOTT','T',cascade=>true); -->收集统计信息 SQL> analyze table t compute statistics; -->收集统计信息 SQL> @Tab_Stat -->此时对象上的统计信息无任何变化,即高水位线没有发生任何变化 Enter value for input_table_name: t Enter value for input_owner: scott NUM_ROWS BLKS EM_BLKS AVG_SPACE CHAIN_CNT AVG_ROW_LEN AVG_ROWS_PER_BLOCK LST_ANLY STA ---------- ---------- ---------- ---------- ---------- ----------- ------------------ --------- --- 100 387 125 7921 0 262 0 03-NOV-11 NO SQL> set autotrace traceonly SQL> select count(*) from t; -->SQL的执行计划中预估的值准确,为100行 Execution Plan ---------------------------------------------------------- Plan hash value: 2966233522 ------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | ------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 86 (0)| 00:00:02 | | 1 | SORT AGGREGATE | | 1 | | | | 2 | TABLE ACCESS FULL| T | 100 | 86 (0)| 00:00:02 | ------------------------------------------------------------------- Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 375 consistent gets -->consistent gets的值仍然为375,并没有下降 0 physical reads SQL> set autotrace off; SQL> alter table t enable row movement; -->启用row movement SQL> alter table t shrink space cascade; --> 实施shrink space SQL> alter table t disable row movement; SQL> exec dbms_stats.gather_table_stats('SCOTT','T'); SQL> analyze table t compute statistics; SQL> @Tab_Stat -->此时对象上的统计信息已发生变化,已使用的块为4块,空闲块为4块 Enter value for input_table_name: t Enter value for input_owner: scott NUM_ROWS BLKS EM_BLKS AVG_SPACE CHAIN_CNT AVG_ROW_LEN AVG_ROWS_PER_BLOCK LST_ANLY STA ---------- ---------- ---------- ---------- ---------- ----------- ------------------ --------- --- 100 4 4 7921 0 259 25 03-NOV-11 NO SQL> set autotrace traceonly SQL> select count(*) from t; Execution Plan ---------------------------------------------------------- Plan hash value: 2966233522 ------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | ------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 3 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | | | | 2 | TABLE ACCESS FULL| T | 100 | 3 (0)| 00:00:01 | ------------------------------------------------------------------- Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 6 consistent gets -->表段收缩之后,consistent gets由375下降为6 0 physical reads SQL> truncate table t; -->使用表截断技术(turncate table) Table truncated. SQL> exec dbms_stats.gather_table_stats('SCOTT','T'); -->收集统计信息 PL/SQL procedure successfully completed. SQL> select count(*) from t; -->此时执行计划中的rows变为1 Execution Plan ---------------------------------------------------------- Plan hash value: 2966233522 ------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | ------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | | | | 2 | TABLE ACCESS FULL| T | 1 | 2 (0)| 00:00:01 | ------------------------------------------------------------------- Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 3 consistent gets -->consistent gets的值降为3 0 physical reads

三、总结
  1、高水线直接决定了全表扫描所需要的I/O开销
  2、delete操作不会降低高水位线,高水位线之下的所有块依然被扫描
  3、使用truncate 会重置高水位线到0位
  4、定期使用alter table tab_name shrink space cascade 有效减少该对象上的I/O开销

你可能感兴趣的:(sql,NoSQL,table,delete,input,statistics)