本文转自


今天用到了Oracle表的分区,就顺便写几个例子把这个表的分区说一说:

一、创建分区表

1、范围分区

根据数据表字段值的范围进行分区

举个例子,根据学生的不同分数对分数表进行分区,创建一个分区表如下:



[sql]  view plain copy print ?


1. create table range_fraction  
2.   (  
3.   id number(8),  
4. name varchar2(20),  
5.   fraction number(3),  
6.   grade number(2)  
7. )  
8. partition by range(fraction)  
9. (  
10. values less than(60), --不及格  
11. values less than(85), --及格  
12. values less than(maxvalue) --优秀  
13. )


创建完分区表后向表中添加一些数据:


[sql]  view plain copy print ?



    1. declare   
    2. name     varchar2(10);  
    3.   fraction number(5);  
    4.   grade    number(5);  
    5.   i        number(8):=1;  
    6. begin  
    7. for i in 1..100000 LOOP  
    8. SELECT CHR (ROUND (DBMS_RANDOM.VALUE (97, 122))) INTO NAME FROM DUAL;  
    9. SELECT ABS(MOD(DBMS_RANDOM.RANDOM,101)) into fraction FROM DUAL;  
    10. SELECT ABS(MOD(DBMS_RANDOM.RANDOM,10))+1 into grade FROM DUAL;  
    11. insert into range_fraction values(seq_range_fraction.nextval ,name,fraction,grade);  
    12. END LOOP;  
    13. end;



    查询分区表:

    [sql]  view plain copy print ?



      1. --分别查询所有的,不及格的,中等的,优秀的成绩  
      2. select *  from  range_fraction;  
      3. select *  from  range_fraction partition(fraction_60) ;  
      4. select *  from  range_fraction partition(fraction_80) ;  
      5. select *  from  range_fraction partition(fraction_100) ;


      当我们的查询语句不指定分区的时候,如果分区字段出现在where条件之后,Oracle会自动根据字段值的范围扫描响应的分区:

      select *  from  range_fraction  where fraction<30;    这句SQL执行的时候只会扫描不及格的分区

      select *  from  range_fraction  where fraction<80;    这句SQL执行的时候会扫描不及格和中等两个分区


      2、散列分区

      在范围分区中,分区字段的连续值通常出现在一个分区内,而在散列分区中,连续的字段值不一定存储在相同的分区中。散列分区把记录分布在比范围分区更多的分区上,这减少了I/O争用的可能性。

      为了创建一个散列分区,应该用partition by hash语句代替partition by range子句,如下所示:

      第一种为各个分区指定不同的表空间,表空间数量不用等于分区数量,当表空间数量大于分区数量的时候会循环写入各个表空间:


      [sql]  view plain copy print ?


      1. <span style="font-family:SimSun;font-size:10px;">create table range_fraction1  
      2.   (  
      3.   id number(8),  
      4. name varchar2(20),  
      5.   fraction number(3),  
      6.   grade number(2)  
      7. )  
      8. partition by hash(fraction)  
      9. partitions 8  
      10. store in (users,tbs_haicheng)</span>

      第二种为每个分区指定一个分区名称并为其指定表空间:


      [sql]  view plain copy print ?


      1. create table range_fraction1  
      2.   (  
      3.   id number(8),  
      4. name varchar2(20),  
      5.   fraction number(3),  
      6.   grade number(1)  
      7. )  
      8. partition by hash(fraction)  
      9. (  
      10.    partition p1 tablespace tbs_haicheng ,  
      11.    partition p2 tablespace users  
      12. );



      3、列表分区

      还可以使用列表分区代替范围分区和散列分区。在列表分区中,告诉Oracle所有可能的值,并指定应当插入相应行的分区。

      我们将1、2、3、4班级的数据放在一个分区,将6、7、8的数据放在一个分区,将其他的再放在一个分区,建表如下:


      [sql]  view plain copy print ?



        1. <span style="font-family:SimSun;font-size:10px;">create table range_fraction1  
        2.   (  
        3.   id number(8),  
        4. name varchar2(20),  
        5.   fraction number(3),  
        6.   grade number(2)  
        7. )  
        8. partition by list(grade)  
        9. (  
        10. values(1,2,3,4) tablespace tbs_haicheng ,  
        11. values(5,6,7,8) tablespace users,</span>


        [sql]  view plain copy print ?


        1. <span style="font-family:SimSun;font-size:10px;">   partition p3 values(default)</span>

        [sql]  view plain copy print ?


        1. <span style="font-family:SimSun;font-size:10px;">);</span>


        4、组合分区(创建子分区)

        即分区的分区。例如可以先进行范围分区,再对各个范围分区创建列表分区。

        对于非常大的表来说,这种组合分区是一种把数据分成可管理和可调整的组成部分的有效方法。

        举个例子:按照分数范围分区后再将ID散列分区:


        [sql]  view plain copy print ?



          1. <span style="font-family:SimSun;font-size:10px;">create table range_fraction1  
          2.   (  
          3.   id number(8),  
          4. name varchar2(20),  
          5.   fraction number(3),  
          6.   grade number(1)  
          7. )  
          8. partition by range(fraction)  
          9. subpartition by hash(id)  
          10. subpartitions 4  
          11.   
          12. (  
          13. values less than(60), --不及格  
          14. values less than(85), --及格  
          15. values less than(maxvalue) --优秀  
          16. )</span>



          二、索引分区


          在分区表上可以建立三种类型的索引:1和普通表一样的全局索引;2.全局分区索引;3.本地分区索引


          1.建立普通的索引

          [sql]  view plain copy print ?


          1. create index index_fraction on range_fraction(fraction);


          2.建立本地分区索引(就是一个索引分区只能对应一个表分区)


          [sql]  view plain copy print ?


          1. create index  local_index_fraction on range_fraction(fraction) local;

          3.建立全局分区索引(属于散列索引分区,就是一个索引分区可能指向多个表分区)


          [sql]  view plain copy print ?


          1. create index global_index_fraction on range_fraction(fraction)  
          2. GLOBAL partition by  range(fraction)  
          3. (  
          4. values less than(1000),  
          5. values less than(MAXVALUE)  
          6. );

          三、管理分区表

          1、增加分区

          对于范围分区来说,添加一个分区,必须该分区划定的界限高于原来的最大界限,也就是说只能往上加,不能往下加。那么对于用maxvalue关键字创建的范围分区就不能增加分区了

          举例:


          [sql]  view plain copy print ?


          1. create table range_fraction  
          2.   (  
          3.   id number(8),  
          4. name varchar2(20),  
          5.   fraction number(3),  
          6.   grade number(2)  
          7. )  
          8. partition by range(fraction)  
          9. (  
          10. values less than(40), --不及格  
          11. values less than(60), --及格  
          12. values less than(80) --优秀  
          13. )


          对于该分区我们增加一个分区:


          [sql]  view plain copy print ?


          为列表分区添加一个分区:

          1. ALTER TABLE range_fraction ADD PARTITION fraction_100 VALUES LESS THAN (100);



          [sql]  view plain copy print ?



            1. create table range_fraction  
            2.   (  
            3.   id number(8),  
            4. name varchar2(20),  
            5.   fraction number(3),  
            6.   grade number(2)  
            7. )  
            8. partition by list(grade)  
            9. (  
            10. values(1,2,3) tablespace tbs_haicheng ,  
            11. values(4,5,6) tablespace users  
            12. );


            [sql]  view plain copy print ?


            1. ALTER TABLE range_fraction ADD partition p3 VALUES (7,8);

            我们再为p3分区新增两个表分区值:

            [sql]  view plain copy print ?



              1. ALTER TABLE range_fraction MODIFY PARTITION p3 ADD VALUES(9,10);


              然后再将p3分区的表分区值中的10删掉:

              [sql]  view plain copy print ?


              1. ALTER TABLE range_fraction MODIFY PARTITION p3 DROP VALUES(10);

              [sql]  view plain copy print ?



              为哈希分区添加一个子分区:


              [sql]  view plain copy print ?


              1. ALTER TABLE TABLENAME ADD PARTITION PARTNAME;

              添加一个子分区的格式:


              [sql]  view plain copy print ?


              1. ALTER TABLE TABLENAME MODIFY PARTITION PARTNAME ADD SUBPARTITION SUBPARTNAME;

              2、删除分区

              删除分区比较简单,格式如下:


              [sql]  view plain copy print ?


              1. ALTER TABLE ... DROP PARTITION part_name;

              3、分区合并

              合并父分区格式:


              [sql]  view plain copy print ?


              1. ALTER TABLE TABLENAME MERGE PARTITIONS p1-1, p1-2 INTO PARTITION p1 UPDATE INDEXES;

              如果省略了UPDATE INDEXES 的话需要为受影响的分区重建索引


              合并子分区的格式:


              [sql]  view plain copy print ?


              1. ALTER TABLE TABLENAME  
              2. MERGE SUBPARTITIONS part_1_sub_2, part_1_sub_3 INTO SUBPARTITION part_1_sub_2 UPDATE INDEXES;

              4、转换分区

              可以将分区表转换成非分区表,或者几种不同分区表之间的转换。如下:


              [sql]  view plain copy print ?



                1. <span style="font-family:SimSun;font-size:10px;">CREATE TABLE hash_part02 AS SELECT * FROMhash_example WHERE 1=2;  
                2. ALTER TABLE hash_example EXCHANGE PARTITIONpart02 WITH TABLE hash_part02;</span>


                这时,分区表hash_example中的part02分区的资料将被转移到hash_part02这个非分区表中。