oracle HWM

  1. Oracle表段中的高水位線HWM : 
  2. 在Oracle數據的存儲中,可以把存儲空間想象爲一個水庫,數據想象爲水庫中的水。 
  3. 水庫中的水的位置有一條線叫做水位線,在Oracle中,這條線被稱爲高水位線(High-warter mark,  
  4.  
  5. HWM)。 
  6.  
  7. 在數據庫表剛建立的時候,由於沒有任何數據,所以這個時候水位線是空的,也就是說HWM爲最低值 
  8.  
  9. 。當插入了數據以後,高水位線就會上漲,但是這裏也有一個特性,就是如果你採用delete語句刪 
  10.  
  11. 除數據的話,數據雖然被刪除了,但是高水位線卻沒有降低,還是你剛纔刪除數據以前那麼高的水 
  12.  
  13. 位。也就是說,這條高水位線在日常的增刪操作中只會上漲,不會下跌。HWM通常增長的幅度爲一次 
  14.  
  15. 5個數據塊. 
  16.  
  17.  
  18. Select語句會對錶中的數據進行一次掃描,但是究竟掃描多少數據存儲塊呢,這個並不是說數據庫 
  19.  
  20. 中有多少數據,Oracle就掃描這麼大的數據塊,而是Oracle會掃描高水位線以下的數據塊。 
  21.  
  22. 理解高水位的作用:理解全表掃描的開銷(實驗:如果) 
  23.  
  24.  
  25. @@@@@@ 
  26. 修正ORACLE表的高水位線 
  27. ORACLE中,執行對錶的刪除操作不會降低該表的高水位線。而全表掃描將始終讀取一個段(extent) 
  28.  
  29. 中所有低於高水位線標記的塊。如果在執行刪除操作後不降低高水位線標記,則將導致查詢語句的 
  30.  
  31. 性能低下。rebuild, truncate, shrink,move  等操作會降低高水位。 
  32.  
  33. A、執行表重建指令 alter table table_name move;(把樓移到另一塊地) 
  34. B、 執行alter table table_name shrink space; 此命令爲Oracle 10g新增功能,再執行該指令之 
  35.  
  36. 前必須允許行移動 alter table table_name enable row movement; 
  37.  
  38. C、 重建表 
  39. 複製要保留的數據到臨時表t,drop原表,然後rename臨時表t爲原表 
  40. D、 用邏輯導入導出: Emp/Imp 
  41. E、. Alter  table table_name deallocate unused   
  42. DEALLOCATE UNUSED爲釋放HWM上面的未使用空間,但是並不會釋放HWM下面的自由空間,也不會移動 
  43.  
  44. HWM的位置.  
  45. F、 推薦使用truncate
  46. @@@@@ 
  47. ORACLE用HWM來界定一個段中使用的塊和未使用的塊. 
  48. 舉個例子來說,當我們創建一個表時,ORACLE就會爲這個對象分配一個段.在這個段中,即使我們未插 
  49.  
  50. 入任何記錄,也至少有一個區被分配,第一個區的第一個塊就稱爲段頭(SEGMENT HEADE),段頭中就儲 
  51.  
  52. 存了一些信息,其中HWM的信息就存儲在此.此時,因爲第一個區的第一塊用於存儲段頭的一些信息,雖 
  53.  
  54. 然沒有存儲任何實際的記錄,但也算是被使用,此時HWM是位於第2個塊.當我們不斷插入數據到表後, 
  55.  
  56. 第1個塊已經放不下後面新插入的數據,此時,ORACLE將高水位之上的塊用於存儲新增數據,同時,HWM 
  57.  
  58. 本身也向上移.也就是說,當我們不斷插入數據時,HWM會往不斷上移,這樣,在HWM之下的,就表示使用 
  59.  
  60. 過的塊,HWM之上的就表示已分配但從未使用過的塊. 
  61.  
  62. HWM在插入數據時,當現有空間不足而進行空間的擴展時會向上移,但刪除數據時不會往下移. 
  63. ORACLE 不會釋放空間以供其他對象使用,有一條簡單的理由:由於空間是爲新插入的行保留的,並 
  64.  
  65. 且要適應現有行的增長。被佔用的最高空間稱爲最高使用標記 (HWM), 
  66.  
  67. @@@ 
  68. ORACLE的全表掃描是讀取高水位標記(HWM)以下的所有塊. 
  69. @@@ 
  70. 什麼樣的插入是在高水位上面進行插入的?(append操作(不檢查高水位線是否有數據,效率高, 
  71.  
  72. 不寫日誌,浪費空間)) 
  73.  
  74. 當用直接路徑插入行時,即使HWM以下有空閒的數據庫塊,鍵入在插入數據時使用了append關鍵字, 
  75.  
  76. 則在插入時使用HWM以上的數據塊,此時HWM會自動增大。 
  77.  
  78.  例如,通過直接加載插入(用 APPEND 提示插入)或通過 SQL*LOADER 直接路徑 數據塊直接置於  
  79.  
  80. HWM 之上。它下面的空間就浪費掉了。 
  81.  
  82. @@@@ 
  83. 相關測試: 
  84. SQL> create table tt (id number);此時表沒有分析,是原始的數據,即8個數據塊。 
  85.  
  86. SQL> select segment_name,segment_type,blocks from dba_segments where segment_nam 
  87. e='TT'
  88.  
  89. SEGMENT_NAME 
  90. -------------------------------------------------------------------------------- 
  91.  
  92. SEGMENT_TYPE           BLOCK 
  93. ------------------ ---------- 
  94. TT 
  95. TABLE                       8(段佔用了多少個塊) 
  96.  
  97.  
  98. SQL> select table_name,num_rows,blocks,empty_blocks from user_tables where table 
  99. _name='TT'
  100.  
  101. TABLE_NAME                       NUM_ROWS     BLOCKS EMPTY_BLOCKS 
  102. ------------------------------ ---------- ---------- ------------ 
  103. TT 
  104.  
  105.  
  106. declare 
  107.      i number; 
  108.  
  109.     begin 
  110.  
  111.     for i in 1..10000 loop 
  112.  
  113.     insert into tt values(i); 
  114.  
  115.     end loop; 
  116.  
  117.    commit
  118.  
  119.    end
  120.  
  121.     / 
  122.  
  123.  
  124. SQL>  SELECT segment_name,segment_type,blocks FROM dba_segments  WHERE  
  125.  
  126. segment_name='TT'
  127.  
  128.   
  129.  
  130. SEGMENT_NAME    SEGMENT_TYPE        BLOCKS 
  131.  
  132. --------------- --------------- ---------- 
  133.  
  134. TT              TABLE                   24 
  135.  
  136. 註釋:user_dbasegments中的BLOCKS 列代表該表中曾經使用過得數據庫塊的數目 
  137.     dba_dbasegments中的BLOCKS 列代表段佔用多少個塊 
  138. SQL> SELECT table_name,num_rows,blocks,empty_blocks FROM user_tables  WHERE  
  139.  
  140. table_name='TT'
  141.  
  142.  
  143. TABLE_NAME        NUM_ROWS     BLOCKS EMPTY_BLOCKS 
  144.  
  145. --------------- ---------- ---------- ------------ 
  146.  
  147. TT 
  148.  
  149.  
  150.  
  151. 此時表TT 佔用的數據庫已經是24個了。 但是user_tables 顯示的信息還是爲空。 因爲沒有做統計 
  152.  
  153. 分析。 
  154. exec DBMS_STATS.GATHER_TABLE_STATS('SYS','TT');(收集統計信息) 
  155.  
  156. SQL> exec DBMS_STATS.GATHER_TABLE_STATS('SYS','TT');(收集統計信息) 
  157.  
  158. PL/SQL 過程已成功完成。 
  159.  
  160.  
  161. SQL> SELECT table_name,num_rows,blocks,empty_blocks FROM user_tables  WHERE  
  162.  
  163. table_name='TT'
  164.  
  165.   
  166.  
  167. TABLE_NAME        NUM_ROWS     BLOCKS EMPTY_BLOCKS 
  168.  
  169. --------------- ---------- ---------- ------------ 
  170.  
  171. TT                   10000         20            0 
  172.  
  173.   
  174.  
  175. 此時user_tables 已經有了數據,顯示的使用了20個數據塊。 但是empty_blocks 還是爲空。  
  176. 這裏要注意的地方。 這個字段只有使用analyze 收集統計信息之後纔會有數據。 
  177.  
  178.  
  179.  
  180. 5) 使用analyze 收集統計信息 
  181. SQL> ANALYZE TABLE TT COMPUTE STATISTICS
  182.  
  183. Table analyzed. 
  184. SQL> SELECT table_name,num_rows,blocks,empty_blocks FROM user_tables  WHERE  
  185.  
  186. table_name='TT'
  187.  
  188.   
  189.  
  190. TABLE_NAME        NUM_ROWS     BLOCKS EMPTY_BLOCKS 
  191.  
  192. --------------- ---------- ---------- ------------ 
  193.  
  194. TT                   10000         20            3 
  195.  
  196. 這個時候高水位在哪裏呢?20(20+3=23<24) 這裏有顯示空的數據庫有3個。   
  197. 注意:20+3=23. 比佔用的24個數據塊少一個。因爲有一個數據庫塊被保留用作segment header。 
  198.  
  199.  
  200. delete 數據 
  201. 看是否會影響他的段大小 
  202. delete from tt; 
  203. commit 
  204.  
  205. SQL>  SELECT segment_name,segment_type,blocks FROM dba_segments  WHERE  
  206.  
  207. segment_name='TT'
  208.  
  209.   
  210.  
  211. SEGMENT_NAME    SEGMENT_TYPE        BLOCKS 
  212.  
  213. --------------- --------------- ---------- 
  214.  
  215. TT              TABLE                   24 
  216.  
  217.  
  218. SQL>analyze table tt compute statistics;(算出高水位線在那一塊) 
  219.  
  220.  
  221. SQL> select table_name,num_rows,blocks,empty_blocks from user_tables where table 
  222. _name='TT';(blocks爲高水位線) 
  223.  
  224. TABLE_NAME                       NUM_ROWS     BLOCKS EMPTY_BLOCKS 
  225. ------------------------------ ---------- ---------- ------------ 
  226. TT                                      0         20            3 
  227.  
  228. 這裏我們可以證明了什麼:高水位不受delete 影響 
  229.  
  230. SQL>insert into tt select * from tt;(tt已經刪除沒有數據) 
  231.  
  232. SQL> insert into tt select rownum from dba_objects; 
  233.  
  234. 已創建50323行。 
  235.  
  236. SQL>analyze table tt compute statistics
  237.  
  238. SQL> select table_name,num_rows,blocks,empty_blocks from user_tables where table 
  239. _name='TT';(查看高水位線(blocks))大於20 
  240.  
  241. TABLE_NAME                       NUM_ROWS     BLOCKS EMPTY_BLOCKS 
  242. ------------------------------ ---------- ---------- ------------ 
  243. TT                                  50323         79            0 
  244. 這裏我們可以證明了什麼:高水位不受commit影響,只要有插入數據HWM就會增加 
  245. @@@@@ 
  246. 釋放高水位(truncate) 
  247.  
  248. SQL> truncate table tt; 
  249.  
  250. 表被截斷。 
  251.  
  252. SQL> ANALYZE TABLE TT COMPUTE STATISTICS
  253.  
  254. 表已分析。 
  255.  
  256. SQL> select segment_name,segment_type,blocks from dba_segments where segment_nam 
  257. e='TT'
  258.  
  259. SEGMENT_NAME 
  260. -------------------------------------------------------------------------------- 
  261.  
  262. SEGMENT_TYPE           BLOCKS 
  263. ------------------ ---------- 
  264. TT 
  265. TABLE                       8(又回到原來的8) 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章