【原創】ORACLE 資料分析和動態取樣

luckyfriends發表於2014-08-12

ORACLE 資料分析和動態取樣》

引言:oracle 資料庫效能調優最需要重視的也最常遇到的就是SQL執行效率,而反映SQL效率最直觀的工具就是CBO生成的執行計劃,那麼如何讓CBO生成最精準的效率最高的執行計劃成為我們當前需要研究的課題。同一條語句,好的執行計劃能帶來飛一樣的速度,壞的執行計劃讓我們痛苦不堪,下面我們從原理到實踐來把如何產生高效計劃的方法教給大家。


  CBO介紹

CBO全稱叫Cost Based optimization基於代價最佳化器,它是一個數學模型,同一個SQL語句在不同的oracle版本中計算出來的代價結果也是不一樣的,因為每個版本CBO最佳化器的設計結構有很大不同,現在還不是很完善很智慧很通人性,因此我們不能完全依賴它,只能輔助我們。

如何生成精確的執行計劃:公式資料+CBO=執行計劃,傳入CBO的資料越精確得到結果越精確,我們能做的保證輸入資料更準確,透過精確資料計算出精確執行計劃


二演示一個表分析後執行計劃比動態取樣更準確的例子

動態取樣:顧名思義就是oracle自動為你進行的初步資料分析,由於是隨機在表上取一些資料,因此並不能保證得出的執行計劃很準確,只能作為一種輔助分析手段,在不得已的情況下來分析資料,有一定的侷限性。

場景:當表沒有分析資訊時,oracle會使用動態取樣技術,而且動態取樣是在SQL硬解析的時候發生的,傳入->CBO引數->生成執行計劃。

級別:oracle 10g   oracle 11g 預設動態取樣級別是2,它有level1-10,設定的級別越高採集的資料塊越多,結果越精確,執行時間越長,level10對所有資料進行取樣分析。

實驗

LEO1@LEO1> drop table leo1 purge;清理環境

Table dropped.

LEO1@LEO1> drop table leo2 purge;

Table dropped.

LEO1@LEO1> create table leo1 as select * from dba_objects;建立leo1

Table created.

LEO1@LEO1> create table leo2 as select * from leo1;建立leo2表,採用leo1一樣資料和結構

Table created.

LEO1@LEO1> col segment_name for a10

LEO1@LEO1> select segment_name,extents,blocks from dba_segments where segment_name in ('LEO1','LEO2');

SEGMENT_NA    EXTENTS     BLOCKS

---------- ---------- -------------- -------------- ----

LEO1               24       1152

LEO2               24       1152

查詢leo1leo2表這兩個段物件儲存引數,都是佔用24個區,1152個塊,2個表一模一樣嘛

LEO1@LEO1> col table_name for a10

LEO1@LEO1> select table_name,num_rows,blocks,status from dba_tables wheretable_name in ('LEO1','LEO2');

TABLE_NAME   NUM_ROWS     BLOCKS STATUS

---------- ---------- ---------- ------------ ---------- ------------

LEO1                             VALID

LEO2                             VALID

在這個資料字典裡只顯示錶名和當前狀態(有效),沒有行資訊和塊資訊,這是為神馬呢,嗯從上面的操作可以看出,我們只是建立了表,但沒有分析表統計資訊,現在我們分析一下後看看效果

LEO1@LEO1> execute dbms_stats.gather_table_stats('LEO1','LEO1');LEO1表進行統計分析

PL/SQL procedure successfully completed.

LEO1@LEO1> select table_name,num_rows,blocks,status from dba_tables wheretable_name in ('LEO1','LEO2');

TABLE_NAME   NUM_ROWS     BLOCKS STATUS

---------- ---------- ---------- ------------ ---------- ------------

LEO1                    71968                 1051       VALID

LEO2                                                              VALID

現在leo1表已經有行資訊和塊資訊了,leo2由於沒有進行表分析現在還什麼都沒有

LEO1@LEO1> set autotrace trace exp

LEO1@LEO1> select * from leo1 where object_id=10000;

Execution Plan

----------------------------------------------------------

Plan hash value: 2716644435

--------------------------------------------------------------------------

| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |

--------------------------------------------------------------------------

|   0 | SELECT STATEMENT  |      |     1 |    97 |   287   (1)| 00:00:04 |

|*  1 |  TABLE ACCESS FULL| LEO1 |    1 |    97 |   287   (1)| 00:00:04 |

--------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

  1 - filter("OBJECT_ID"=10000)

Leo1表進行了統計分析,執行計劃顯示Rows=1,嗯由於object_id欄位是不重複的,我們都知道object_id=10000只有一條記錄,這和執行計劃的判斷結果是一致,所以表分析可以讓oracle收集表資料的資訊,讓CBO瞭解表資料分佈情況,有多少條,佔用多少空間等。
總之“分析”就是讓oracle理解我們的資料是怎麼樣一個情況,以便更好的去處理它

LEO1@LEO1> select * from leo2 where object_id=10000;

Execution Plan

----------------------------------------------------------

Plan hash value: 2258638698

--------------------------------------------------------------------------

| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |

--------------------------------------------------------------------------

|   0 | SELECT STATEMENT  |      |    12 |  2484 |   287   (1)| 00:00:04 |

|*  1 |  TABLE ACCESS FULL| LEO2 |    12 |  2484 |   287   (1)| 00:00:04 |

--------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

  1 - filter("OBJECT_ID"=10000)

Note

-----

   - dynamic sampling used for this statement (level=2)

Leo2表沒有進行統計分析,oracle採用了動態取樣技術(紅色字顯示),執行計劃顯示Rows=12,由於動態取樣只是隨機在表上取一些資料來評估,沒有進行全表完整分析,固然得出的執行計劃沒有leo1表更精確更好。所以說“動態取樣”只是一個補救措施。


三演示在缺乏直方圖(柱狀圖)時,CBO計算出錯誤的執行計劃的例子,並給出最後正確的執行計劃

直方圖(柱狀圖):oracle對列上的資料分佈情況進行統計,得出的圖示。

場合:常用於檢視資料傾斜情況(一個值在整個欄位中所佔比例),瞭解某個鍵值所擁有的記錄數

如果是數字1這個鍵值在整個欄位中佔用的比例

如果是字元leonarding這個鍵值在整個欄位中佔用的比例

如果是日期    2012-12-21 這個日期在整個欄位中佔用的比例

直方圖型別:

1Frequency-頻率直方圖:用於基數少,記錄多,重複率高的欄位

2Height Balanced-高度平衡直方圖:用於基數多,唯一值多,重複率低的欄位,這個就是等分相同資料量的桶(bucket),值可能不同,來顯示桶中記錄數的比例

實驗

LEO1@LEO1> drop table leo3 purge;清除環境

Table dropped.

LEO1@LEO1> drop table leo4 purge;

Table dropped.

LEO1@LEO1> create table leo3 as select * from dba_objects;建立leo3

Table created.

LEO1@LEO1> create table leo4 as select * from dba_objects;建立leo4

Table created.

LEO1@LEO1> execute dbms_stats.gather_table_stats('LEO1','LEO3',method_opt=>'for all columns size 1');

PL/SQL procedure successfully completed.

LEO1@LEO1> execute dbms_stats.gather_table_stats('LEO1','LEO4',method_opt=>'for all columns size 254');

PL/SQL procedure successfully completed.

leo3表做資訊收集但沒有做直方圖分析(for all columns size 11 代表不做直方圖

leo4表做資訊收集但又做了直方圖分析(for all columns size 254254 代表最精確直方圖對所有列都做分析,在分析表時把更多資料告訴CBO,得出最精確的執行計劃。

注:刪除表上分析資訊語句

LEO1@LEO1> execute dbms_stats.delete_table_stats('LEO1','LEO3');

PL/SQL procedure successfully completed.

LEO1@LEO1> select table_name,column_name,num_distinct,num_buckets,histogram from dba_tab_col_statistics where table_name in ('LEO3','LEO4');

TABLE_NAME COLUMN_NAME              NUM_DISTINCT NUM_BUCKETS HISTOGRAM

---------- ------------------------------ ------------ ----------- ---------------

LEO3       EDITION_NAME                              0           0 NONE

LEO3       NAMESPACE                                   20           1 NONE

LEO3       SECONDARY                                   2           1 NONE

LEO3       GENERATED                                  2           1 NONE

LEO3       TEMPORARY                                 2           1 NONE

LEO3       STATUS                                           2           1 NONE

LEO3       TIMESTAMP                                 1227           1 NONE

LEO3       LAST_DDL_TIME                         1170           1 NONE

LEO3       CREATED                                       1097           1 NONE

LEO3       OBJECT_TYPE                               43           1 NONE

LEO3       DATA_OBJECT_ID                      7262           1 NONE

LEO3       OBJECT_ID                                   71966           1 NONE

LEO3       SUBOBJECT_NAME                           58           1 NONE

LEO3       OBJECT_NAME                           43424           1 NONE

LEO3       OWNER                                        24           1 NONE

LEO4       EDITION_NAME                              0           0 NONE

LEO4       NAMESPACE                                20          14 FREQUENCY

LEO4       SECONDARY                                 2           2 FREQUENCY

LEO4       GENERATED                                 2           2 FREQUENCY

LEO4       TEMPORARY                                 2           2 FREQUENCY

LEO4       STATUS                                          2           1 FREQUENCY

LEO4       TIMESTAMP                                1228         254 HEIGHT BALANCED

LEO4       LAST_DDL_TIME                        1171         254 HEIGHT BALANCED

LEO4       CREATED                                      1098         254 HEIGHT BALANCED

LEO4       OBJECT_TYPE                              43          30 FREQUENCY

LEO4       DATA_OBJECT_ID                      7263         254 HEIGHT BALANCED

LEO4       OBJECT_ID                                   71967         254 HEIGHT BALANCED

LEO4       SUBOBJECT_NAME                           58          58 FREQUENCY

LEO4       OBJECT_NAME                           43424         254 HEIGHT BALANCED

LEO4       OWNER                                        24          19 FREQUENCY

30 rows selected.

引數說明:

TABLE_NAME:表名  leo3我們沒有做直方圖分析顯示NONE   leo4做了

COLUMN_NAME:列名

NUM_DISTINCT:列中不同鍵值數(就是我們所說基數)

NUM_BUCKETS:直方圖的桶數,用幾個桶來裝資料

HISTOGRAM:直方圖型別,FREQUENCY and HEIGHT BALANCED

例對於status列由於基數少重複率很高則使用frequency直方圖

對於object_id由於都是唯一值沒有重複率則使用height balance直方圖

與我們上面寫的情況一致

LEO1@LEO1> select count(*) from leo3 where object_type='TABLE';標準記錄數2816

COUNT(*)

-----------------

      2816

LEO1@LEO1> select count(*) from leo3 where object_type='TABLE';

Execution Plan

----------------------------------------------------------

Plan hash value: 3505406240

---------------------------------------------------------------------------

| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |

---------------------------------------------------------------------------

|   0 | SELECT STATEMENT   |      |     1 |     9 |   287   (1)| 00:00:04 |

|   1 |  SORT AGGREGATE    |      |     1 |     9 |            |          |

|*  2 |   TABLE ACCESS FULL| LEO3 | 1674 | 15066 |   287   (1)| 00:00:04 |

---------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

   2 - filter("OBJECT_TYPE"='TABLE')

由於leo3我們沒有做直方圖分析,CBO就不知道object_type='TABLE'在整個欄位中所佔比例,導致Rows=1674與標準2816偏差太大,這就是沒有足夠分析資料的結果

LEO1@LEO1> select count(*) from leo4 where object_type='TABLE';

Execution Plan

----------------------------------------------------------

Plan hash value: 3210696650

---------------------------------------------------------------------------

| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |

---------------------------------------------------------------------------

|   0 | SELECT STATEMENT   |      |     1 |     9 |   287   (1)| 00:00:04 |

|   1 |  SORT AGGREGATE    |      |     1 |     9 |            |          |

|*  2 |   TABLE ACCESS FULL| LEO4 | 2697 | 24273 |   287   (1)| 00:00:04 |

---------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

   2 - filter("OBJECT_TYPE"='TABLE')

由於leo4做了全表整體直方圖分析,生成254個桶來裝資料,oracle必然瞭解object_type='TABLE'在整個欄位中所佔比例,Rows=2697 和標準2816 已經非常接近了,相對比較精確,這就是有足夠分析資料的結果。


四演示在分割槽表上,全域性資訊和分割槽資訊是如何影響執行計劃的,給出演示過程

全域性統計資訊:如果跨分割槽CBO使用全域性統計資訊

分割槽統計資訊:如果不跨分割槽CBO使用分割槽統計資訊

全域性資訊和分割槽資訊是2個獨立資訊源,某些情況下會有聯絡

實驗

LEO1@LEO1> drop table leo5 purge;清除環境

Table dropped.

LEO1@LEO1> drop table leo6 purge;

Table dropped.

LEO1@LEO1> create table leo5建立一個分割槽表

partition by range (object_id)

(

partition p1 values less than(10000),

partition p2 values less than(20000),

partition p3 values less than(30000),

partition p4 values less than(40000),

partition p5 values less than(50000),

partition p6 values less than(60000),

partition pm values less than(maxvalue)

) as select * from dba_objects;  2    3    4    5    6    7    8    9   10   11  

Table created.

LEO1@LEO1> execute dbms_stats.gather_table_stats('LEO1','LEO5');預設對全域性和分割槽都做分析

PL/SQL procedure successfully completed.

LEO1@LEO1> select table_name,num_rows,blocks,global_stats from dba_tables where table_name in ('LEO5');

TABLE_NAME   NUM_ROWS     BLOCKS GLO

---------- ---------- ---------- ----- ---------- ---------- ------------ ------

LEO5         71979       1111 YES

從全域性上看,Leo5表有71979行記錄佔用1111個塊

LEO1@LEO1> select table_name,partition_name,num_rows,blocks,global_stats from dba_tab_partitionswhere table_name='LEO5';

TABLE_NAME PARTITION_NAME                   NUM_ROWS     BLOCKS GLO

---------- ------------------------------ ---------- ---------- ---

LEO5       P1                                   9708        137 YES

LEO5       P2                                   9806        152 YES

LEO5       P3                                  10000        158 YES

LEO5       P4                                  10000        159 YES

LEO5       P5                                  10000        159 YES

LEO5       P6                                   9606        150 YES

LEO5       PM                                  12859        196 YES

從分割槽上看,每個分割槽有多少行記錄佔用了多少個資料塊,總和應該與全域性資訊一致

NUM_ROWS:是一個估算值

LEO1@LEO1> execute dbms_stats.gather_table_stats('LEO1','LEO5',granularity=>'partition');

PL/SQL procedure successfully completed.

Granularity引數:針對分割槽表來說的,在哪個粒度上做分析

Global:全域性級別分析

Partition:分割槽級別分析

Subpartition:子分割槽級別分析

我們這條命令單獨對分割槽做分析,更新分割槽統計資訊,不更新全域性統計資訊

LEO1@LEO1> select table_name,num_rows,blocks,global_stats from dba_tables where table_name in ('LEO5');

TABLE_NAME   NUM_ROWS     BLOCKS GLO

---------- ---------- ---------- ------------ ---------- ---------------

LEO5          71979       1111 YES

全域性統計資訊沒有變化,與實際資料資訊不相符了

LEO1@LEO1> select table_name,partition_name,num_rows,blocks,global_stats from dba_tab_partitions where table_name='LEO5';

TABLE_NAME PARTITION_NAME                   NUM_ROWS     BLOCKS GLO

---------- ------------------------------ ---------- ---------- ---

LEO5       P1                                  19416        382 YES

LEO5       P2                                  19612        382 YES

LEO5       P3                                  20000        382 YES

LEO5       P4                                  20000        382 YES

LEO5       P5                                  20000        382 YES

LEO5       P6                                  19212        382 YES

LEO5       PM                                  25718        382 YES

分割槽統計資訊已經被更新了

現在看一下統計資訊是如何被使用的

LEO1@LEO1> select count(*) from leo5 where object_id<8000;符合條件有15668

COUNT(*)

------------------

     15668

LEO1@LEO1> select count(*) from leo5 where object_id<8000;

Execution Plan

----------------------------------------------------------

Plan hash value: 546738359

------------------------------------------------------------------------------------------------

| Id  | Operation               | Name | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |

------------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT    |    |     1 |     4 |105   (0)| 00:00:02 |       |       |

|   1 |  SORT AGGREGATE |   |     1|     4 |      |       |       |       |

|   2 |   PARTITION RANGE SINGLE|   | 15534 | 62136 |   105   (0)| 00:00:02 |     1 |     1 |

|*  3 |    TABLE ACCESS FULL   | LEO5 | 15534 | 62136 |   105   (0)| 00:00:02 |     1 |     1 |

------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

   3 - filter("OBJECT_ID"<8000)

由於我們在分割槽級別重新進行了分析,分割槽統計資訊是最新版,CBO使用了最新分割槽統計資訊後Rows=15534 與實際15668 已經相差無疑,基本上得出的是正確結果。

原理:我們說過如果不跨分割槽CBO使用分割槽統計資訊,針對某個分割槽oracle獲取資訊

Pstart| Pstop起始分割槽和結束分割槽都是1,說明結果集都落在了第一個分割槽只需掃描第一個分割槽即可

LEO1@LEO1> select count(*) from leo5 where object_id<30001;符合條件有59030

COUNT(*)

----------------

     59030

LEO1@LEO1> select count(*) from leo5 where object_id<30001;

Execution Plan

----------------------------------------------------------

Plan hash value: 3650668575

--------------------------------------------------------------------------------------------------

| Id  | Operation                 | Name | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |

--------------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT     |      |     1 |     5 |   416   (1)| 00:00:05 |       |       |

|   1 |  SORT AGGREGATE |      |     1 |     5 |       |          |       |       |

|   2 |   PARTITION RANGE ITERATOR| | 29209 |   142K|   416   (1)| 00:00:05 |     1 |     4 |

|*  3 |    TABLE ACCESS FULL  | LEO5 | 29209 |   142K|   416   (1)| 00:00:05 |     1 |     4 |

--------------------------------------------------------------------------------------------------

4個分割槽掃描

Predicate Information (identified by operation id):

---------------------------------------------------

  3 - filter("OBJECT_ID"<30001)

LEO1@LEO1> select count(*) from leo5 where object_id<30000;   

Execution Plan

----------------------------------------------------------

Plan hash value: 3650668575

--------------------------------------------------------------------------------------------------

| Id  | Operation                 | Name | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |

--------------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT    |      |     1 |     5 |   313   (1)| 00:00:04 |       |       |

|   1 |  SORT AGGREGATE |      |     1 |     5 |            |          |       |       |

|   2 |   PARTITION RANGE ITERATOR|  | 29208 |   142K|   313   (1)| 00:00:04 |     1 |     3 |

|   3 |    TABLE ACCESS FULL   | LEO5 | 29208 |   142K|   313   (1)| 00:00:04 |     1 |     3 |

--------------------------------------------------------------------------------------------------

3個分割槽掃描

小結:只要跨分割槽CBO就使用全域性統計資訊,由於全域性資訊過舊,不管掃描3個分割槽還是4個分割槽Rows=29209 這與實際值59030都相差甚遠,這就是為什麼分割槽裡資料是準的,而全域性裡資料是不準的。

我們再一次對全域性級別分析一次看看全域性統計資訊是不是更新了,執行計劃是不是精準了

LEO1@LEO1> execute dbms_stats.gather_table_stats('LEO1','LEO5',granularity=>'global');

PL/SQL procedure successfully completed.

LEO1@LEO1> select table_name,num_rows,blocks,global_stats from dba_tables where table_name in ('LEO5');

TABLE_NAME   NUM_ROWS     BLOCKS GLO

---------- ---------- ---------- ------ ---------- ---------- --------

LEO5           143958       2674 YES

這次全域性統計資訊更新了

LEO1@LEO1> select count(*) from leo5 where object_id<30001;

Execution Plan

----------------------------------------------------------

Plan hash value: 3650668575

--------------------------------------------------------------------------------------------------

|Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |

--------------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT  |      |     1 |     5 |   416   (1)| 00:00:05 |       |       |

|   1 |  SORT AGGREGATE |      |     1 |     5 |            |          |       |       |

|   2 |   PARTITION RANGE ITERATOR|  | 58418 |   285K|   416   (1)| 00:00:05 |     1 |     4 |

|*  3 |    TABLE ACCESS FULL | LEO5 | 58418 |   285K|   416   (1)| 00:00:05 |     1 |     4 |

--------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

   3 - filter("OBJECT_ID"<30001)

小結:我們使用更新後的全域性統計資訊得出Rows=58418 與實際值59030差不多了,說明單獨對分割槽分析,不會更新全域性統計資訊。


五演示用extended statistics 解決列相關性的例子,給出演示過程

列的相關性:就是where子句中同時存在2個列以上條件時,CBO不做列與列之間相關性分析,這會導致CBO計算執行計劃出現一種偏差

實驗

由於oracle11g之前 CBO不做列與列之間相關性分析,我的實驗環境是11g的沒有10g環境,我們就用其他方式模擬一下吧。

LEO1@LEO1> select count(*) from leo6 where object_type='TABLE' and wner='LEO1';

COUNT(*)

------------------

        20符合條件有20

LEO1@LEO1> select count(*) from leo6 where object_type='TABLE' and wner='LEO1';

Execution Plan

----------------------------------------------------------

Plan hash value: 3995977415

---------------------------------------------------------------------------

| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |

---------------------------------------------------------------------------

|   0 | SELECT STATEMENT   |      |     1 |    28 |   287   (1)| 00:00:04 |

|   1 |  SORT AGGREGATE   |      |     1 |    28 |            |          |

|*  2 |   TABLE ACCESS FULL| LEO6 |    8 |   224 |   287   (1)| 00:00:04 |

---------------------------------------------------------------------------

CBO不做列與列之間相關性分析前提下,Rows=8顯然CBO計算錯誤,應該有20行的

LEO1@LEO1>

executedbms_stats.gather_table_stats('LEO1','LEO6',method_opt=>'for columns (object_type,owner) size skewonly');

PL/SQL procedure successfully completed.

我們對leo6表做列相關性分析,看看CBO計算是否準確

LEO1@LEO1> select count(*) from leo6 where object_type='TABLE' and wner='SYS';

COUNT(*)

----------------

       969符合條件有969

LEO1@LEO1> select count(*) from leo6 where object_type='TABLE' and wner='SYS';

Execution Plan

----------------------------------------------------------

Plan hash value: 3995977415

---------------------------------------------------------------------------

| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |

---------------------------------------------------------------------------

|   0 | SELECT STATEMENT   |      |     1 |    28 |   287   (1)| 00:00:04 |

|   1 |  SORT AGGREGATE   |      |     1 |    28 |            |          |

|*  2 |   TABLE ACCESS FULL| LEO6 |   819 | 22932 |   287   (1)| 00:00:04 |

---------------------------------------------------------------------------

小結:這次CBORows=819與實際值969非常接近了,可以看出作完列與列相關性分析後,CBO知道2個列的資料分佈情況是一個什麼樣子了,從而在計算執行計劃上有更多資料參考得出結果更準確。


六對一張表進行匯出/匯入,看它的統計資訊是否發生改變,給出演示過程。

LEO1@LEO1> drop table leo7 purge;清除環境

Table dropped.

LEO1@LEO1> create table leo7 as select * from dba_objects;建立leo7

Table created.

LEO1@LEO1> execute dbms_stats.gather_table_stats('LEO1','LEO7');進行表分析

PL/SQL procedure successfully completed.

LEO1@LEO1> select count(*) from leo7;現在我們表裡有71979行記錄

COUNT(*)

-----------------

71979

LEO1@LEO1> select table_name,num_rows,blocks,global_stats from dba_tables where table_name in ('LEO7');

TABLE_NAME   NUM_ROWS     BLOCKS GLO

---------- ---------- ---------- ---- ---------- ----------- -----

LEO7            71979       1051 YES

做完表分析後,統計資訊已經有了,有71979行,1051個塊,只包括資料段

LEO1@LEO1> select segment_name,extents,blocks from dba_segmentswhere segment_name in ('LEO7');

SEGMENT_NA    EXTENTS     BLOCKS

---------- ---------- ----------- ---------- -----------

LEO7               24       1152

這是leo7段物件的儲存引數,佔用24個區1152個資料塊,段物件裡面的塊數包括資料段+表頭段的資訊

[oracle@leonarding1 ~]$ expuserid=leo1/leo1@leo1 file=/home/oracle/leo7_dump_file1.dmp tables=leo7 rows=y

Export: Release 11.2.0.1.0 - Production on Sun Jan 20 14:16:45 2013

Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.

Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production

With the Partitioning, OLAP, Data Mining and Real Application Testing options

Export done in US7ASCII character set and AL16UTF16 NCHAR character set

server uses ZHS16GBK character set (possible charset conversion)

About to export specified tables via Conventional Path ...

. . exporting table                           LEO7      71979 rows exported

EXP-00091: Exporting questionable statistics.

Export terminated successfully with warnings.

匯出leo7表進行匯出

[oracle@leonarding1 ~]$ ll

total 8208

drwxrwxrwx 8 oracle oinstall    4096 Aug 21  2009 database

drwxr-xr-x 2 oracle oinstall    4096 Nov 17 14:48 Desktop

-rw-r--r-- 1 oracle oinstall       7 Nov 17 15:43 em

-rw-r--r-- 1 oracle oinstall 8314880 Jan 20 14:16 leo7_dump_file1.dmp

-rw-r--r-- 1 oracle oinstall   42201 Dec 16 21:25 orahdfs-1.0.0.0.0.zip

-rwxrwxrwx 1 oracle oinstall     795 Dec 16 23:53 test1.txt

-rwxrwxrwx 1 oracle oinstall   13325 Dec 27 23:13 test.txt

看一下統計資訊,現在沒有變化,也就是說匯出不會更新表統計資訊

LEO1@LEO1> select table_name,num_rows,blocks,global_stats from dba_tables where table_name in ('LEO7');

TABLE_NAME   NUM_ROWS     BLOCKS GLO

---------- ---------- ---------- ---

LEO7            71979       1051 YES

我們把leo7_dump_file1.dmp在匯入到leo7表中

[oracle@leonarding1 ~]$ imp userid=leo1/leo1@leo1 file=/home/oracle/leo7_dump_file1.dmp full=y ignore=y

Import: Release 11.2.0.1.0 - Production on Sun Jan 20 14:31:12 2013

Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.

Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production

With the Partitioning, OLAP, Data Mining and Real Application Testing options

Export file created by EXPORT:V11.02.00 via conventional path

import done in US7ASCII character set and AL16UTF16 NCHAR character set

import server uses ZHS16GBK character set (possible charset conversion)

. importing LEO1's objects into LEO1

. importing LEO1's objects into LEO1

. . importing table                         "LEO7"      71979 rows imported

Import terminated successfully without warnings.

LEO1@LEO1> select count(*) from leo7;

COUNT(*)

----------------

143958

預設追加方式匯入資料,原來71979行,匯入後143958

LEO1@LEO1> select table_name,num_rows,blocks,global_stats from dba_tables where table_name in ('LEO7');

TABLE_NAME   NUM_ROWS     BLOCKS GLO

---------- ---------- ---------- ---------- ---------- ----------

LEO7            71979       1051 YES

我們對leo7表進行了追加匯入,但是它的統計資訊還是原來收集的統計資訊,也就是說匯入也不會更新表統計資訊

LEO1@LEO1> execute dbms_stats.gather_table_stats('LEO1','LEO7');

PL/SQL procedure successfully completed.

LEO1@LEO1> select table_name,num_rows,blocks,global_stats from dba_tables where table_name in ('LEO7');

TABLE_NAME   NUM_ROWS     BLOCKS GLO

---------- ---------- ---------- ---

LEO7           143958       2160 YES

小結:只有重新進行表分析才能更新表統計資訊


動態取樣 直方圖  CBO  gather  granularity  extendedstatisticsexp  imp  列相關性



2013.1.20
天津&winter
分享技術~成就夢想

Blog

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

相關文章