Oracle 11g维护分区(五)——Merging Partitions
合并分区
使用ALTER TABLE ... MERGE PARTITION语句将两个分区的内容合并到一个分区。原来的两个分区将会被删除,相关的本地索引也会被删除。对于哈希分区表或者复合哈希分区表的哈希子分区,你不能使用这个语句。
对于引用分区表,你不能合并分区。相反,父表的合并操作会级联到所有子表。尽管如此,当你在父表执行合并分区或者子分区操作时,你也可以使用DEPENDENT TABLES子句来为相关表设置特定属性。
如果涉及到的分区或者子分区包含数据,那么索引可能被标识为UNUSABLE,如下表所述:
表类型 | 索引操作 |
普通表(堆表) | 除非你在ALTER TABLE语句中指定UPDATE INDEXES字句: l 数据库将生成的所有相关本地索引分区或者子分区标识为UNUSABLE。 l 全局索引,或者分区全局索引的所有分区,被标识为UNUSABLE,必须重建。 |
索引组织表 | l 生成的所有相关本地索引分区标识为UNUSABLE。 l 所有全局索引保持可用。 |
合并范围分区
你可以将两个相邻的范围分区的内容合并到一个分区。不相邻的范围分区不能合并。合并生成的分区继承了这两个合并分区中更高的上限。
合并范围分区的一个原因是保持在线历史数据在较大的分区。例如,你可以有每日分区,然后将最旧的分区聚合为周分区,进而周分区可以聚合为月分区,等等。
例4-31显示了一个合并范围分区的例子。
例4-31 合并范围分区
- -- First, create a partitioned table with four partitions, each on its own
- -- tablespace partitioned by range on the data column
- --
- CREATE TABLE four_seasons
- (
- one DATE,
- two VARCHAR2(60),
- three NUMBER
- )
- PARTITION BY RANGE ( one )
- (
- PARTITION quarter_one
- VALUES LESS THAN ( TO_DATE('01-apr-1998','dd-mon-yyyy'))
- TABLESPACE quarter_one,
- PARTITION quarter_two
- VALUES LESS THAN ( TO_DATE('01-jul-1998','dd-mon-yyyy'))
- TABLESPACE quarter_two,
- PARTITION quarter_three
- VALUES LESS THAN ( TO_DATE('01-oct-1998','dd-mon-yyyy'))
- TABLESPACE quarter_three,
- PARTITION quarter_four
- VALUES LESS THAN ( TO_DATE('01-jan-1999','dd-mon-yyyy'))
- TABLESPACE quarter_four
- );
- --
- -- Create local PREFIXED index on Four_Seasons
- -- Prefixed because the leftmost columns of the index match the
- -- Partitioning key
- --
- CREATE INDEX i_four_seasons_l ON four_seasons ( one,two )
- LOCAL (
- PARTITION i_quarter_one TABLESPACE i_quarter_one,
- PARTITION i_quarter_two TABLESPACE i_quarter_two,
- PARTITION i_quarter_three TABLESPACE i_quarter_three,
- PARTITION i_quarter_four TABLESPACE i_quarter_four
- );
- -- Next, merge the first two partitions
- ALTER TABLE four_seasons
- MERGE PARTITIONS quarter_one, quarter_two INTO PARTITION quarter_two
- UPDATE INDEXES;
如果你省略了上述语句中的UPDATE INDEXES子句,那么你必须重建受影响分区的本地索引。
- -- Rebuild index for quarter_two, which has been marked unusable
- -- because it has not had all of the data from Q1 added to it.
- -- Rebuilding the index corrects this.
- --
- ALTER TABLE four_seasons MODIFY PARTITION
- quarter_two REBUILD UNUSABLE LOCAL INDEXES;
合并间隔分区
你可以将两个相邻的间隔分区的内容合并到一个分区。不相邻的间隔分区不能合并。第一个间隔分区也能喝最高的范围分区进行合并。合并生成的分区继承了这两个合并分区中更高的上限。
合并间隔分区总是导致转换点移动到这两个合并分区中更高的上限。结果是间隔分区表的范围分区扩展到这两个合并分区中更高的上限。任何边界低于新合并生成分区的物化间隔分区,都会自动转化到范围分区,并且使用它们的间隔分区上限定义作为范围分区上限。
例如,考虑一下间隔分区transactions:
- CREATE TABLE transactions
- ( id NUMBER
- , transaction_date DATE
- , value NUMBER
- )
- PARTITION BY RANGE (transaction_date)
- INTERVAL (NUMTODSINTERVAL(1,'DAY'))
- ( PARTITION p_before_2007 VALUES LESS THAN (TO_DATE('01-JAN-2007','dd-MON-yyyy')));
把数据插入到该表的间隔分区部分,这将会创建这些日期的间隔分区。需要注意的是,2007年1月15日和2007年1月16日的数据被存储到相邻的间隔分区。
- INSERT INTO transactions VALUES (1,TO_DATE('15-JAN-2007','dd-MON-yyyy'),100);
- INSERT INTO transactions VALUES (2,TO_DATE('16-JAN-2007','dd-MON-yyyy'),600);
- INSERT INTO transactions VALUES (3,TO_DATE('30-JAN-2007','dd-MON-yyyy'),200);
接下来,合并两个相邻的间隔分区。新分区会再有一个系统生成的名称。
- ALTER TABLE transactions
- MERGE PARTITIONS FOR(TO_DATE('15-JAN-2007','dd-MON-yyyy'))
- , FOR(TO_DATE('16-JAN-2007','dd-MON-yyyy'));
对于transactions表而言,转换点现在已经移动到了2007年1月17日。该间隔分区表的范围分区部分包含两个范围分区:值小于2007年1月1日,以及值小于2007年1月17日。值大于2007年1月17日的数据将会存储在间隔分区表的间隔分区部分。
合并列表分区
当你合并列表分区时,本合并的分区可以是任意两个分区。它们不必像范围分区那样必须是相邻的,因为列表分区默认是没有顺序的。生成的分区由原来两个分区的数据组成。如果你将默认分区和其他分区进行合并,那么新生成的分区是默认分区。
下面的语句合并了一个列表分区表的两个分区,新生成的分区继承了所有表级别的默认属性。语句指定了MAXEXTENTS子句。
- ALTER TABLE q1_sales_by_region
- MERGE PARTITIONS q1_northcentral, q1_southcentral
- INTO PARTITION q1_central
- STORAGE(MAXEXTENTS 20);
- 原来的两个分区的值列表如下:
- PARTITION q1_northcentral VALUES ('SD','WI')
- PARTITION q1_southcentral VALUES ('OK','TX')
- 由此生成的sales_west分区值列表包括这两个分区值列表的集合,更具体的说:
- ('SD','WI','OK','TX')
合并复合哈希分区
当你合并复合哈希分区时,子分区会根据哈希函数重新分布到由SUBPARTITIONS n或者SUBPARTITIONS子句指定数量的分区。如果两个都没有指定,那么就使用表级别的默认值。
需要注意的是,分割一个复合哈希分区(在“分割一个复合哈希分区”章节讨论)和合并两个复合哈希分区,在属性的继承方面是不一样的。当一个分区被分割时,新的分区可以继承原分区的属性,因为只有一个父节点。但是,当合并分区时,必须继承表级别属性。
对于间隔哈希分区表,你只能合并两个相邻的间隔分区,或者时最高范围分区和第一个间隔分区。如“合并间隔分区”所述,当你在间隔哈希分区表合并分区时,转换点时会移动的。
下面的例子合并了两个范围哈希分区:
点击(此处)折叠或打开
- ALTER TABLE all_seasons
- MERGE PARTITIONS quarter_1, quarter_2 INTO PARTITION quarter_2
- SUBPARTITIONS 8;
合并复合列表分区
你可以在分区级别合并分区,也可以在列表子分区级别合并子分区。
在一个复合列表分区表中合并分区
在复合列表分区表中合并分区如前面所论述的“合并范围分区”。但是,当你合并两个复合列表分区时,生成的新分区将继承子分区模版的子分区描述,前提是该模版存在。如果不存在子分区模版,那么将为新分区创建一个默认子分区。
对于间隔哈希分区表,你只能合并两个相邻的间隔分区,或者时最高范围分区和第一个间隔分区。如“合并间隔分区”所述,当你在间隔哈希分区表合并分区时,转换点时会移动的。
下面的语句合并了范围列表分区表stripe_regional_sales的两个分区。该表存在一个子分区模版。
- ALTER TABLE stripe_regional_sales
- MERGE PARTITIONS q1_1999, q2_1999 INTO PARTITION q1_q2_1999
- STORAGE(MAXEXTENTS 20);
对于新的分区,我们指定了一些新的物理属性,同时,对于那些没有指定的属性将会继承表级别的默认值。新生成的分区q1_q2_1999将会继承q2_1999分区的上限边界,并且子分区的值列表描述将会继承该表的子分区模版描述。
新生成分区的数据由两个分区的数据组成。但是,可能存在数据库返回错误的情况。这个之所以会发生,可能是因为当同时满足下列条件时,数据可能会映射到新分区之外:
- 合并后子分区的一些值可能并不属于子分区模版。
- 子分区模版不包含默认分区定义。
我们可以通过在默认子分区模版中指定一个默认分区来消除这个错误条件。
在一个复合列表分区表中合并子分区
你可以合并同一分区中的任意两个列表子分区的内容。由此生成的子分区值列表描述包括所有被合并分区的值。
下面的语句合并了范围列表分区表的两个子分区,并将新生成的子分区保存到表空间ts4:
- ALTER TABLE quarterly_regional_sales
- MERGE SUBPARTITIONS q1_1999_northwest, q1_1999_southwest
- INTO SUBPARTITION q1_1999_west
- TABLESPACE ts4;
原始的两个分区的值列表如下:
- 子分区q1_1999_northwest被描述为('WA','OR')
- 子分区q1_1999_southwest被描述为('AZ','NM','UT')
新生成子分区的值列表由上述两个子分区值列表的合集构成:
- 子分区q1_1999_west被描述为('WA','OR','AZ','NM','UT')
新生成子分区的存储表空间以及子分区属性都由分区级别的默认属性决定,除非你显式地指定。
如果任何现有地子分区名称被重复使用,那么新生成子分区将会继承名称被重复使用子分区的属性。
合并复合范围分区
你可以在分区级别合并分区,也可以在范围子分区级别合并子分区。
在一个复合范围分区表中合并分区
在复合范围分区表中合并分区如前面所论述的“合并范围分区”。但是,当你合并两个复合范围分区时,生成的新分区将继承子分区模版的子分区描述,前提是该模版存在。如果不存在子分区模版,那么将会创建一个上限边界是MAXVALUE的新分区。
对于间隔范围分区表,你只能合并两个相邻的间隔分区,或者时最高范围分区和第一个间隔分区。如“合并间隔分区”所述,当你在间隔哈希分区表合并分区时,转换点时会移动的。
下面的语句合并了月份间隔范围分区表orders的两个分区。该表存在一个子分区模版。
- ALTER TABLE orders
- MERGE PARTITIONS FOR(TO_DATE('01-MAR-2007','dd-MON-yyyy')),
- FOR(TO_DATE('01-APR-2007','dd-MON-yyyy'))
- INTO PARTITION p_pre_may_2007;
如果2007年3月和4月的分区仍然在间隔范围分区表的间隔部分,那么合并操作将会把转换点移动到2007年5月1日。
对于分区p_pre_may_2007而言,所有子分区都将从子分区模版中继承他们的属性。新生成分区的数据由两个分区的数据组成。但是,可能存在数据库返回错误的情况。这个之所以会发生,可能是因为当同时满足下列条件时,数据可能会映射到新分区之外:
- 合并后子分区的一些值可能并不属于子分区模版。
- 子分区模版不包含一个上限边界值为MAXVALUE的子分区定义。
我们可以通过在子分区模版中指定一个上限边界值为MAXVALUE的子分区来消除这个错误条件。