zoukankan      html  css  js  c++  java
  • oracle表分区详解(按天、按月、按年等)



    分区表的概念:
      
    当表中的数据量不断增大,查询数据的速度就会变慢,应用程序的性能就会下降,这时就应该考虑对表进行分区。表进行分区后,逻辑上表仍然是一张完整的表,只是将表中的数据在物理上存放到多个表空间(物理文件上),这样查询数据时,不至于每次都扫描整张表。


    分区表的优点:


    1)   改善查询性能:对分区对象的查询可以仅搜索自己关心的分区,提高检索速度。


    2)   增强可用性:如果表的某个分区出现故障,表在其他分区的数据仍然可用;


    3)   维护方便:如果表的某个分区出现故障,需要修复数据,只修复该分区即可;


    4)   均衡I/O:可以把不同的分区映射到磁盘以平衡I/O,改善整个系统性能。


    分区表的种类:


    1.范围分区
    概念: 范围分区将数据基于范围映射到每一个分区,这个范围是你在创建分区时指定的分区键决定的。这种分区方式是最为常用的,并且分区键经常采用日期。举个例子:你可能会将销售数据按照月份进行分区。




    -- 按行分区
    SQL> CREATE TABLE part_andy1
      2  (
      3      andy_ID NUMBER NOT NULL PRIMARY KEY,
      4      FIRST_NAME  VARCHAR2(30) NOT NULL,
      5      LAST_NAME   VARCHAR2(30) NOT NULL,
      6      PHONE        VARCHAR2(15) NOT NULL,
      7      EMAIL        VARCHAR2(80),
      8      STATUS       CHAR(1)
      9  )
     10  PARTITION BY RANGE (andy_ID)
     11  (
     12      PARTITION PART1 VALUES LESS THAN (10000) ,
     13      PARTITION PART2 VALUES LESS THAN (20000)
     14  );


    Table created.


    -- 按时间分区


    SQL> CREATE TABLE part_andy2
      2  (
      3  ORDER_ID      NUMBER(7) NOT NULL,
      4  ORDER_DATE    DATE,
      5  OTAL_AMOUNT NUMBER,
      6  CUSTOTMER_ID NUMBER(7),
      7  PAID           CHAR(1)
      8  )
      9  PARTITION BY RANGE (ORDER_DATE)
     10  (
     11    PARTITION p1 VALUES LESS THAN (TO_DATE('2014-10-1', 'yyyy-mm-dd')) ,
     12    PARTITION p2 VALUES LESS THAN (TO_DATE('2015-10-1', 'yyyy-mm-dd')) ,
     13    PARTITION p3 VALUES LESS THAN (TO_DATE('2016-10-1', 'yyyy-mm-dd')) ,
     14    partition p4 values less than (maxvalue)
     15  );


    Table created.


    2.  Hash分区


    概念:
    对于那些无法有效划分范围的表,可以使用hash分区,这样对于提高性能还是会有一定的帮助。hash分区会将表中的数据平均分配到你指定的几个分区中,列所在分区是依据分区列的hash值自动分配,因此你并不能控制也不知道哪条记录会被放到哪个分区中,hash分区也可以支持多个依赖列。


    注意:
    hash分区最主要的机制是根据hash算法来计算具体某条纪录应该插入到哪个分区中,hash算法中最重要的是hash函数,Oracle中如果你要使用hash分区,只需指定分区的数量即可。建议分区的数量采用2的n次方,这样可以使得各个分区间数据分布更加均匀。


    --按hash分区
    SQL> create table part_andy3
      2  (
      3  transaction_id number primary key,
      4  item_id number(8) not null
      5  )
      6  partition by hash(transaction_id)
      7  (
      8  partition part_01 ,
      9  partition part_02 ,
     10  partition part_03
     11  );


    Table created.


    3.  List分区


    概念:
    List分区也需要指定列的值,其分区值必须明确指定,该分区列只能有一个,不能像range或者hash分区那样同时指定多个列做为分区依赖列,但它的单个分区对应值可以是多个。


    注意:
    在分区时必须确定分区列可能存在的值,一旦插入的列值不在分区范围内,则插入/更新就会失败,因此通常建议使用list分区时,要创建一个default分区存储那些不在指定范围内的记录,类似range分区中的maxvalue分区。


    -- 按list分区
    SQL> create table part_andy4
      2  (
      3  id varchar2(15 byte) not null,
      4  city varchar2(20)
      5  )
      6  partition by list (city)
      7  (
      8  partition t_list025 values ('beijing'),
      9  partition t_list372 values ('shanghai') ,
     10  partition t_list510 values ('changsha'),
     11  partition p_other values (default)
     12  );


    Table created.


    4. 组合分区


    Oracle10g提供两种分区组合
    – Range-hash
    SQL> create table part_andy5
      2  (
      3  transaction_id number primary key,
      4  item_id number(8) not null,
      5  item_description varchar2(300),
      6  transaction_date date
      7  )
      8  partition by range(transaction_date)subpartition by hash(transaction_id)
      9  (
     10  partition part_01 values less than(TO_DATE('2014-10-1', 'yyyy-mm-dd')),
     11  partition part_02 values less than(TO_DATE('2015-10-1', 'yyyy-mm-dd')),
     12  partition part_03 values less than(maxvalue)
     13  );


    Table created.






    – Range-list
    SQL> CREATE TABLE SALES
      2  (
      3  PRODUCT_ID VARCHAR2(5),
      4  SALES_DATE DATE,
      5  SALES_COST NUMBER(10),
      6  STATUS VARCHAR2(20)
      7  )
      8  PARTITION BY RANGE(SALES_DATE) SUBPARTITION BY LIST (STATUS)
      9  (
     10  PARTITION P1 VALUES LESS THAN(TO_DATE('2014-10-1', 'yyyy-mm-dd'))
     11  (SUBPARTITION P1SUB1 VALUES ('ACTIVE') ,SUBPARTITION P1SUB2 VALUES ('INACTIVE')
     12  ),PARTITION P2 VALUES LESS THAN (TO_DATE('2015-10-1', 'yyyy-mm-dd'))
     13  (
     14  SUBPARTITION P2SUB1 VALUES ('ACTIVE') ,
     15  SUBPARTITION P2SUB2 VALUES ('INACTIVE')
     16  )
     17  );


    Table created.




     Oracle11g增加了四种组合
    – RANGE-RANGE
    – LIST-RANGE
    – LIST-HASH
    – LIST-LIST 


    Oracle 11g 中虚拟列来实现。在11g之前 分区表的partition key必须是物理存在的。11g开始提供了虚拟列,并且可以作为partition key 。
    --按星期分区 
    SQL> CREATE TABLE part_andy6
      2  (
      3  getdate   date NOT NULL,
      4  wd        NUMBER GENERATED ALWAYS AS (TO_NUMBER (TO_CHAR (getdate, 'D'))) VIRTUAL
      5  )
      6  PARTITION BY LIST (wd)
      7  (
      8  PARTITION Mon  VALUES (1),
      9  PARTITION Tue  VALUES (2),
     10  PARTITION Wed  VALUES (3),
     11  PARTITION Thu  VALUES (4),
     12  PARTITION Fri  VALUES (5),
     13  PARTITION Sat   VALUES (6),
     14  PARTITION Sun  VALUES (7)
     15  );


    Table created.


    SQL>
    SQL> insert into part_andy6(getdate) values(sysdate);


    1 row created.


    SQL> insert into part_andy6(getdate) values(sysdate-1);


    1 row created.


    SQL> insert into part_andy6(getdate) values(sysdate-2);


    1 row created.


    SQL> insert into part_andy6(getdate) values(sysdate-3);


    1 row created.


    SQL> insert into part_andy6(getdate) values(sysdate-4);


    1 row created.


    SQL> insert into part_andy6(getdate) values(sysdate-5);


    1 row created.


    SQL> insert into part_andy6(getdate) values(sysdate-6);


    1 row created.


    SQL> insert into part_andy6(getdate) values(sysdate-7);


    1 row created.


    -- 检查测试成功
    SQL> select * from part_andy6;


    GETDATE                     WD
    ------------------- ----------
    2014-11-23 16:35:07          1
    2014-11-24 16:35:07          2
    2014-11-25 16:35:07          3
    2014-11-26 16:35:07          4
    2014-11-27 16:35:07          5
    2014-11-28 16:35:07          6
    2014-11-29 16:35:07          7
    2014-11-22 16:35:08          7


    8 rows selected.


    Oracle Database 11g,Interval类型分区表,可以根据加载数据,自动创建指定间隔的分区。


    创建按月分区的分区表:


    a. 创建分区表


    SQL> CREATE TABLE interval_andy7 (a1 NUMBER, a2 DATE)
      2  PARTITION BY RANGE (a2)
      3  INTERVAL ( NUMTOYMINTERVAL (1, 'MONTH') )
      4  (PARTITION part1
      5  VALUES LESS THAN (TO_DATE('2014-11-1', 'yyyy-mm-dd')),
      6  PARTITION part2
      7  VALUES LESS THAN (TO_DATE('2014-12-1', 'yyyy-mm-dd'))
      8  );


    Table created.
    注意:如果在建Interval分区表是没有把所有的分区写完成,在插入相关数据后会自动生成分区
    b. 查看现在表的分区:
    SQL> select table_name,partition_name from user_tab_partitions where table_name='INTERVAL_ANDY7';
    TABLE_NAME                     PARTITION_NAME
    ------------------------------ ------------------------------
    INTERVALPART                   PART1
    INTERVALPART                   PART2
    c.  插入测试数据:
    SQL> begin
      2  for i in 0 .. 11 loop
      3  insert into interval_andy7 values(i,add_months(to_date('2014-11-1','yyyy-mm-dd'),i));
      4  end loop ;
      5  commit;
      6  end;
      7  /


    PL/SQL procedure successfully completed.


    PL/SQL 过程已成功完成。
    补充:add_months()函数获取前一个月或者下一个月的月份, 参数中 负数 代表 往前, 正数 代表 往后。
    --上一个月
    select to_char(add_months(trunc(sysdate),-1),'yyyymm') from dual;
    --下一个月 
    select to_char(add_months(trunc(sysdate),1),'yyyymm') from dual;
    d. 观察自动创建的分区:
    SQL> select table_name,partition_name from user_tab_partitions where table_name='INTERVAL_ANDY7';


    TABLE_NAME                     PARTITION_NAME
    ------------------------------ ------------------------------
    INTERVAL_ANDY7                 PART1
    INTERVAL_ANDY7                 PART2
    INTERVAL_ANDY7                 SYS_P24
    INTERVAL_ANDY7                 SYS_P25
    INTERVAL_ANDY7                 SYS_P26
    INTERVAL_ANDY7                 SYS_P27
    INTERVAL_ANDY7                 SYS_P28
    INTERVAL_ANDY7                 SYS_P29
    INTERVAL_ANDY7                 SYS_P30
    INTERVAL_ANDY7                 SYS_P31
    INTERVAL_ANDY7                 SYS_P32


    TABLE_NAME                     PARTITION_NAME
    ------------------------------ ------------------------------
    INTERVAL_ANDY7                 SYS_P33
    INTERVAL_ANDY7                 SYS_P34


    13 rows selected.








    下面创建一个以天为间隔的分区表:


    1. 创建分区表:
    SQL> create table interval_andy8
      2  (
      3  id    number,
      4  dt    date
      5  )
      6  partition by range (dt)
      7  INTERVAL (NUMTODSINTERVAL(1,'day'))
      8  (
      9  partition p20141101 values less than (to_date('2014-11-1','yyyy-mm-dd'))
     10  );


    Table created.


    2. 查看表分区:
    SQL> select table_name,partition_name from user_tab_partitions where table_name='INTERVAL_ANDY8';


    TABLE_NAME                     PARTITION_NAME
    ------------------------------ ------------------------------
    INTERVAL_ANDY8                 P20141101


    3. 插入测试数据:
    begin
    for i in 1 .. 12 loop
    insert into INTERVAL_ANDY8 values(i,trunc(to_date('2014-11-1','yyyy-mm-dd')+i));
    end loop;
    commit;
    end;
    /
    PL/SQL 过程已成功完成。
    4. 观察自动创建的分区:
    SQL> select table_name,partition_name from user_tab_partitions where table_name='INTERVAL_ANDY8';


    TABLE_NAME                     PARTITION_NAME
    ------------------------------ ------------------------------
    INTERVAL_ANDY8                 P20141101
    INTERVAL_ANDY8                 SYS_P35
    INTERVAL_ANDY8                 SYS_P36
    INTERVAL_ANDY8                 SYS_P37
    INTERVAL_ANDY8                 SYS_P38
    INTERVAL_ANDY8                 SYS_P39
    INTERVAL_ANDY8                 SYS_P40
    INTERVAL_ANDY8                 SYS_P41
    INTERVAL_ANDY8                 SYS_P42
    INTERVAL_ANDY8                 SYS_P43
    INTERVAL_ANDY8                 SYS_P44


    TABLE_NAME                     PARTITION_NAME
    ------------------------------ ------------------------------
    INTERVAL_ANDY8                 SYS_P45
    INTERVAL_ANDY8                 SYS_P46


    13 rows selected.


    说明:个人总结+网络博文
    参考: http://blog.csdn.net/tianlesoftware/article/details/5662337

  • 相关阅读:
    HTML5你必须知道的28个新特性
    localStorage使用总结
    Oracle分页查询排序数据重复问题
    servlet,RMI,webservice之间的区别
    远程通信的几种选择(RPC,Webservice,RMI,JMS的区别)
    几种通讯协议的比较
    http、TCP/IP协议与socket之间的区别
    Oracle修改序列(Sequence)起始值问题
    mybatis开启二级缓存小记
    使用canvas绘制渐变色矩形和使用按键控制人物移动
  • 原文地址:https://www.cnblogs.com/andy6/p/6238512.html
Copyright © 2011-2022 走看看