我有一张大桌子.第一个范围由price_date分区,然后由fund_id分区.该表有4.3亿行.每天我都有一个批处理工作,每天插入150万到300万行.
我们正在寻找启用和禁用本地索引(不是所有索引,而是基于数据仅由数据触摸的数据)
有没有人有经验使插入大表运行更快,没有删除和重建技术?
有没有人对这种情况有任何建议?
解决方法
去读这个:
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;