暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 分区选项

askTom 2016-02-22
121

问题描述

我有一个数据库,其中一个表包含历史BLOB数据,所以这个表目前相当大(1.2TB)。我根据ID分区了一个范围,我的主键(此表没有日期列) ,为了便于管理,我将除当前分区以外的所有分区设置为只读。我的目标是使每个分区为10G ,所以我在最初使用dbms_re定义的时候循环访问并确定了用于每个分区的适当ID。由于BLOB的大小变化很大,所以范围到处都是。我的想法是,在DB增长以创建额外的10G只读分区时,我将简单地拆分活动分区,只要确定创建新的10G分区所需的ID即可。我在拆分活动分区时遇到的问题是,拆分所需的时间,以及用户在拆分期间无法继续添加新数据的事实。我不能在这个数据库上有任何停机时间进行分区维护,所以我需要找到一种方法来分割并让应用程序继续运行。根据我的研究,答案是在需要的时候提前向表中添加新的分区,而不是拆分当前的分区,但对我来说,我不想这样做,因为我正试图使它们在大小上有些一致。如有任何建议将不胜感激。

专家解答

这里有一个古老的股票市场说法: "过去的行为不是未来行为的可靠指标"这一点可能适用于这里,因为它只需要几个非常大的斑点,就可以在几行中轻松地将您带到10g ,而明天,可能需要数百万行(每个都有小斑点)才能将您带到10g。所以你可能会有某种妥协。

这种折衷可能依赖于“快速分割”优化,即在分割点的“右侧”一侧选择一个没有数据的点。

这里有一些让你开始的东西-逻辑是这样的:

-按顺序沿着隔板走
-如果“此”分区为空,请检查前一个分区的大小
-如果大于x ,则
-在逻辑点将它拆分为2个分区,以便一个分区拥有所有数据,一个空分区(ptmp)
-将“maxvalue”最高分区拆分为两个( pn和pmax ) ,为分区建立新的合理边界点
-合并ptmp和pn

所以,在数字上,我们说

       values less than          current hwm
p1     1000                      1000
p2     2000                      1500
pmax   maxvalue                  -


我们认为p2现在“太大了”。我们这样做

步骤1 -拆分p2

       values less than          current hwm
p1     1000                      1000
p2     1600                      1500
ptmp   2000                      -
pmax   maxvalue                  -


因此,我们现在将p2限制在1600 (即,在插入过程中保留了一些回旋余地)

步骤2 -拆分pmax

       values less than          current hwm
p1     1000                      1000
p2     1600                      1500
ptmp   2000                      -
p3     3000                      -
pmax   maxvalue                  -


我们这样做是因为ptmp对我们没有好处,因为它的上限是2000 ,我们希望它的上限是一个合理的逻辑值

步骤3 -合并p3和ptmp

       values less than          current hwm
p1     1000                      1000
p2     1600                      1500
p3     3000                      -
pmax   maxvalue                  -


我们就完了。所有这些操作,因为它们在空分区上工作,实际上都是瞬时的。

这里是一个演示,其中30兆是一个片段的大小限制

SQL> create table T ( x int, y char(200))
  2  partition by range (x)
  3  (
  4    partition p1 values less than (300000),
  5    partition p2 values less than (600000),
  6    partition p3 values less than (900000),
  7    partition p4 values less than (1200000),
  8    partition pmax values less than (maxvalue)
  9  );

Table created.

SQL>
SQL> insert /*+ APPEND */ into T
  2  select rownum, rownum
  3  from dual
  4  connect by level <= 1000000;

1000000 rows created.

SQL>
SQL> create index IX on T ( x ) local;

Index created.

SQL>
SQL> alter table T add constraint T_PK primary key ( x ) using index local
  2  /

Table altered.

SQL>
SQL> select bytes
  2  from user_segments
  3  where segment_name = 'T';

     BYTES
----------
  75497472
  75497472
  75497472
  25165824


现在,在另一个会话中,我正在批量运行插入以模拟在线活动

SQL> declare
  2    l_start int;
  3    l_cnt int := 1;
  4  begin
  5    select max(x) into l_start from t;
  6
  7    for i in 1 .. 1000 loop
  8      for j in 1 .. 10000 loop
  9        insert into t values (l_start+l_cnt,i);
 10        l_cnt := l_cnt + 1;
 11      end loop;
 12      commit;
 13      dbms_lock.sleep(4);
 14    end loop;
 15  end;
 16  /


这是我的例行程序,它可以随时监视并自动进行分区维护

SQL> set serverout on
SQL> declare
  2    l_has_Rows int;
  3    l_hi_par  varchar2(30);
  4    l_hi_bytes int;
  5    l_hwm int;
  6
  7    procedure ddl(m varchar2) is
  8    begin
  9      dbms_output.put_line(m);
 10      execute immediate m;
 11    end;
 12  begin
 13    for i in ( select p.partition_name, s.bytes, p.partition_position
 14               from   user_segments s,
 15                      user_tab_partitions p
 16               where  p.table_name= 'T'
 17               and    p.table_name = s.segment_name(+)
 18               and    p.partition_name = s.partition_name(+)
 19               order by p.partition_position asc
 20               )
 21    loop
 22        execute immediate 'select count(*) from t partition ( '||i.partition_name||') where rownum = 1' into l_has_rows;
 23        dbms_output.put_line(i.partition_name||':'||i.bytes||':'||l_has_rows);
 24        if l_has_rows > 0 then
 25          --
 26          -- we've hit a partition with rows
 27          --
 28          if i.partition_name = 'PMAX' then
 29            raise_application_error(-20000,'We got rows in PMAX...thats a problem');
 30          end if;
 31
 32          l_hi_par := i.partition_name;
 33          l_hi_bytes := i.bytes;
 34        else
 35          --
 36          -- see if we've hit PMAX, check size of prev one
 37          --
 38          if l_hi_bytes > 30*1024*1024 then
 39            execute immediate 'select max(x) from t partition ( '||l_hi_par||')' into l_hwm;
 40
 41            ddl('alter table T split partition '||l_hi_par||' at ('||(l_hwm+10000)||') into (partition '||l_hi_par||', partition ptmp)');
 42            ddl('alter table T split partition pmax at ('||(l_hwm+10000+300000)||') into (partition p'||i.partition_position||', partition pmax)');
 43            ddl('alter table T merge partitions ptmp,p'||i.partition_position||' into partition p'||i.partition_position);
 44
 45          end if;
 46          exit;
 47        end if;
 48    end loop;
 49  end;
 50  /
P1:75497472:1
P2:75497472:1
P3:75497472:1
P4:25165824:1
PMAX::0

PL/SQL procedure successfully completed.

SQL>
SQL>
SQL> /
P1:75497472:1
P2:75497472:1
P3:75497472:1
P4:33554432:1
PMAX::0
alter table T split partition P4 at (1020000) into (partition P4, partition ptmp)
alter table T split partition pmax at (1320000) into (partition p5, partition pmax)
alter table T merge partitions ptmp,p5 into partition p5

PL/SQL procedure successfully completed.

SQL> /
P1:75497472:1
P2:75497472:1
P3:75497472:1
P4:33554432:1
P5:8388608:1
PMAX::0

PL/SQL procedure successfully completed.

SQL> /
P1:75497472:1
P2:75497472:1
P3:75497472:1
P4:33554432:1
P5:16777216:1
PMAX::0

PL/SQL procedure successfully completed.

SQL> /
P1:75497472:1
P2:75497472:1
P3:75497472:1
P4:33554432:1
P5:33554432:1
PMAX::0
alter table T split partition P5 at (1140000) into (partition P5, partition ptmp)
alter table T split partition pmax at (1440000) into (partition p6, partition pmax)
alter table T merge partitions ptmp,p6 into partition p6

PL/SQL procedure successfully completed.

SQL> /
P1:75497472:1
P2:75497472:1
P3:75497472:1
P4:33554432:1
P5:33554432:1
P6:8388608:1
PMAX::0

PL/SQL procedure successfully completed.

SQL>


好好享受吧!
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论