2010-08-24 55 views
4

我有一個巨大的表格。第一個範圍按price_date進行分區,然後用fund_id對哈希進行分區。該表有4.3億行。我每天都有一份批量工作,每天插入150萬到300萬行。將數據加載到巨大的分區表

我們正在尋找的用於啓用和禁用本地索引(並非所有的指標,但在此基礎上分區由唯一的數據感動數據)

沒有人有在做插入大表的運行速度沒有下降,重建經驗技術?

有沒有人只對這種情況有任何建議?

+0

你每天都在加載一個新的分區嗎?可能不會。你正在加載到一個現有的分區嗎?幾個不同的分區?大部分現有分區? – APC 2010-08-24 11:43:19

+0

APC的問題除外:所有索引都是本地的嗎? – dpbradley 2010-08-24 14:06:54

回答

4

去閱讀這樣的:

http://www.evdbt.com/TGorman%20TD2005%20DWScale.doc

這工作。

您是否面臨在線查詢或遲到數據(例如,您今天/昨天的任何一天今天能排到哪一行)的挑戰?

我已經得到了掃描我要加載的記錄的數據集的代碼,並且在表子分區將要被修改時標記本地索引子分區。 (我使用這個而不是Tim Gorman的參考文獻,因爲我有遲到的數據,需要同時向最終用戶提供臨時區域和倉庫本身。)

我的表是範圍/列表,而不是範圍/散列。所以你將不得不修改它,可能使用ORA_HASH函數來找到正確的子分區。我還寫了一張表,我將標記爲不可用的子分區,所以我可以一次完成所有這些。在單個ALTER TABLE語句中將所有子分區的索引標記爲不可用可能會稍微高效一些;我最初只禁用BITMAP索引,但即使在數據加載過程中使單個B *樹索引脫機,也可以顯着提高效率。

procedure DISABLE_LOCAL_INDEXES as 
    l_part_name varchar2(30); 
    l_subpart_name varchar2(30); 
    l_sql varchar2(2000); 
    type partition_rec_type is record 
    (table_name   varchar2(30), 
     partition_name  varchar2(30), 
     subpartition_name varchar2(30), 
     list_value   varchar2(10), 
     min_ts    timestamp, 
     max_ts    timestamp); 
    type partition_recs_type 
         is table of partition_rec_type; 
    l_partition_recs partition_recs_type := partition_recs_type(); 
    l_partition_rec  partition_rec_type; 
    l_subpart_id  number := 1; 
    l_start_ts   timestamp; 
    l_end_ts   timestamp; 
    l_found_list_part boolean; 
    begin 
    -- build set of subpartitions 
    l_start_ts := to_timestamp ('1970-01-01', 'yyyy-mm-dd'); 
    for i in (select p.table_name, p.partition_name, sp.subpartition_name, 
         p.high_value as part_high_value, 
         sp.high_value as subpart_high_value, 
         p.partition_position, sp.subpartition_position 
       from user_tab_subpartitions sp 
         inner join user_tab_partitions p 
         on p.table_name  = sp.table_name 
         and p.partition_name = sp.partition_name 
       where p.table_name = 'MY_TARGET_TABLE' 
       order by p.partition_position, sp.subpartition_position) 
    loop 
     if ((i.partition_position <> 1) and (i.subpartition_position = 1)) then 
     l_start_ts := l_end_ts + to_dsinterval('0 00:00:00.000000001'); 
     end if; 
     if (i.subpartition_position = 1) then 
     l_end_ts := high_val_to_ts (i.part_high_value); 
     l_end_ts := l_end_ts - to_dsinterval('0 00:00:00.000000001'); 
     end if; 
     l_partition_rec.table_name  := i.table_name; 
     l_partition_rec.partition_name := i.partition_name; 
     l_partition_rec.subpartition_name := i.subpartition_name; 
     l_partition_rec.list_value  := i.subpart_high_value; 
     l_partition_rec.min_ts   := l_start_ts; 
     l_partition_rec.max_ts   := l_end_ts; 
     l_partition_recs.extend(); 
     l_partition_recs(l_subpart_id) := l_partition_rec; 
     l_subpart_id := l_subpart_id + 1; 
    end loop; 
    -- for every combination of list column and date column 
    -- which is going to be pushed to MY_TARGET_TABLE 
    -- find the subpartition 
    -- otherwise find the partition and default subpartition 
    for i in (select distinct LIST_COLUMN, DATE_COLUMN as DATE_VALUE 
       from MY_SOURCE_TABLE 
       where IT_IS_BEING_MOVED_TO_TARGET IS TRUE) 
    loop 
     -- iterate over the partitions 
     l_found_list_part := false; 
     for k in l_partition_recs.first..l_partition_recs.last 
     loop 
     -- find the right partition/subpartition for list_value/date_value 
     if ( (i.DATE_VALUE >= l_partition_recs(k).min_ts) 
      and (i.DATE_VALUE <= l_partition_recs(k).max_ts)) then 
      if (l_found_list_value = false) then 
      if (to_char(i.LIST_COLUMN, '9999') = l_partition_recs(k).LIST_COLUMN) then 
       l_found_list_value := true; 
      elsif (l_partition_recs(k).LIST_COLUMN = 'DEFAULT') then 
       l_partition_rec := l_partition_recs(k); 
      end if; 
      end if; 
     end if; 
     end loop; -- over l_partition_recs 
     -- log those partitions for later index rebuild 
     begin 
     insert into index_subpart_rebuild 
      (table_name, partition_name, subpartition_name) 
     values 
      (l_partition_rec.table_name, l_partition_rec.partition_name, 
      l_partition_rec.subpartition_name); 
     exception 
     when dup_val_on_index then null; 
     when others then raise; 
     end; 
    end loop; -- over MY_TARGET_TABLE.DATE_VALUE values 
    commit; 
    for i in (select ui.index_name, uis.subpartition_name 
       from user_indexes ui 
         inner join user_ind_subpartitions uis 
         on ui.index_name = uis.index_name 
         inner join index_subpart_rebuild re 
         on re.subpartition_name = uis.subpartition_name 
       where ui.table_name = 'MY_TARGET_TABLE') 
    loop 
     l_sql := 'alter index ' || i.index_name || 
       ' modify subpartition ' || i.subpartition_name || ' unusable'; 
     execute immediate l_sql; 
    end loop; 
    end DISABLE_LOCAL_INDEXES; 
+0

+1。 (不能說這是否解決@ sumanta的問題。) – 2010-08-24 20:11:48

0

我不知道你正在使用的數據庫,

在SQL SERVER的情況下,嘗試創建一個臨時表,將數據裝入該表,這個臨時表建立索引和約束上,並使用

帶SWITCH子句的ALTER TABLE將此作爲新分區添加到當前表中。

相關問題