sql >> データベース >  >> RDS >> Oracle

巨大なパーティションテーブルへのデータロード

    これを読んでください:

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

    これは機能します。

    ステージング領域にオンラインクエリや遅れて到着するデータにアクセスできるようにするという課題がありますか(たとえば、今日/昨日よりも今日の行を取得できますか)

    ロードするレコードのデータセットをスキャンし、テーブルのサブパーティションが変更される場合はローカルインデックスのサブパーティションにマークを付けるコードがあります。 (上記のTim Gormanの参照の代わりにこれを使用しています。これは、到着が遅れたデータがあり、エンドユーザーがステージングエリアとウェアハウスを同時に利用できるようにする必要があるためです。)

    私のテーブルは範囲/リストであり、範囲/ハッシュではありません。したがって、おそらくORA_HASH関数を使用して適切なサブパーティションを見つけるなど、いくつか変更する必要があります。また、使用不可としてマークするサブパーティションをテーブルに書き出すので、すべてを1回のパスで実行できます。単一のALTERTABLEステートメントですべてのサブパーティションのインデックスを使用不可としてマークする方が少し効率的かもしれません。私はもともとBITMAPインデックスを無効にするだけでしたが、データの読み込み中に単一のB * treeインデックスをオフラインにしても、効率が大幅に向上しました。

      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;
    


    1. PHPPDOMySQLトランザクションコード構造

    2. インメモリOLTPデータベースとテーブルの作成とアクセス

    3. 誤った条件が原因で失敗したUPDATEと、値が変更されていないために失敗したUPDATEを区別する

    4. OracleのSYS_GUID()UUID RFC 4122に準拠していますか?