2016-09-27 16 views
1

最近、Oracle 12cのいくつかの大きな表を、日付フィールドとパーティション索引で日単位の範囲パーティションを使用するように変換しました。データロードプロセスの一環として、私は、データが挿入され、コミットされた後に、最後にテーブル上のギャザー統計プロシージャを実行します。インターバルパーティショニングを使用すると、挿入された新しいデータが既存のパーティションの上限のいずれにも属していない場合、新しいパーティションが自動的に作成されるため、簡単に作成できます。しかし、私は、集計統計処理を実行するのに要する時間が重要であることに気付きました。行数が数百万にもなるテーブルの場合、多くの時間がかかります。事は:大部分のデータは変更されないので、新しいパーティションやデータが変更されたパーティションの統計情報を収集することにのみ関心があります。私はそれができる方法はありますか?Oracle 12c:新しいパーティションの統計のみを収集する

+0

あなたは、単純な新しいパーティションフォーム前のフル・パーティションに統計をコピーすることができます。 –

答えて

1

これはincremental statisticsがために建てられた、まさにです。

増分統計では、変更されたパーティションのパーティション統計のみが収集されます。シナプスは各パーティションごとに作成され、これらのシナリオはすばやく結合されてテーブル全体を再スキャンせずにグローバル統計を作成します。

これを有効にするには、テーブル設定を設定して統計情報を収集する必要があります。最初の収集は遅くなりますが、将来の統計収集はずっと高速になります。

begin 
    dbms_stats.set_table_prefs('TABLE_OWNER', 'TABLE_NAME', 'incremental', 'true'); 
    dbms_stats.gather_table_stats('TABLE_OWNER', 'TABLE_NAME'); 
end; 
/
2

ここに行きます。パーティションの値で統計を収集するためのスクリプト。多分それはあなたを助けます:

declare 
    v_table_name varchar2(64) := ''; --your table 
    v_key_value number := ; -- your range value 

    v_data_object_id number; 
    v_object_name varchar2(64); 
    v_object_type varchar2(64); 
    v_granularity varchar2(64); 
    v_part_name varchar2(64); 
begin 
    begin 
    for i in (select kc.column_name 
       from user_part_key_columns kc 
       where kc.name = upper(v_table_name) 
       and kc.object_type = 'TABLE') 
    loop 
     execute immediate 'select /*+ first_rows */ dbms_rowid.rowid_object(rowid) 

          from ' || v_table_name || ' 
          where '|| i.column_name || ' = '|| v_key_value || 
          ' and rownum = 1' 
     into v_data_object_id; 
    end loop; 
    exception 
    when no_data_found then 
     v_data_object_id := null; 
    end; 

    begin 
    select t.subobject_name, t.OBJECT_TYPE 
     into v_object_name, v_object_type 
    from user_objects t 
    where t.data_object_id = v_data_object_id; 
    exception 
     when no_data_found then 
     v_object_name := null; 
    end; 

    if v_object_name is null 
    then 
     dbms_output.put_line ('no data found'); 
    else 
     if v_object_type = 'TABLE SUBPARTITION' 
     then 
      v_granularity := 'SUBPARTITION'; 

      select t.partition_name 
      into v_part_name 
      from user_tab_subpartitions t 
      where t.subpartition_name = v_object_name; 

     else 
      v_granularity := 'PARTITION'; 
      v_part_name := v_object_name; 
     end if; 

     dbms_stats.gather_table_stats (ownname => user 
            ,tabname => upper(v_table_name) 
            ,partname => v_part_name 
            ,granularity => v_granularity 
            ,cascade => true 
            ,no_invalidate => false); 
    end if; 
end; 
0

別の簡単な解決策は、この1のようになります。

BEGIN 
FOR aPart IN (SELECT TABLE_NAME, PARTITION_NAME FROM USER_TAB_PARTITIONS WHERE TABLE_NAME = 'YOUR_TABLE' AND LAST_ANALYZED IS NULL) LOOP 
    DBMS_STATS.GATHER_TABLE_STATS(USER, aPart.TABLE_NAME, aPart.PARTITION_NAME); 
END LOOP; 
END; 
関連する問題