Oracle 表分区详解(partition table)

1 概述

1. 目的:提高大表的查询效率

2. 概念:将一个表划分为多个分区表,"分而治之"

3. 优缺点
   优点:
   (1) '改善查询性能': 分区对象的查询仅搜索自己关系的分区
   (2) '增强可用性'  : 如果某个分区出现故障,其它分区的数据仍然可用
   (3) '维护方便'    : 如果某个分区出现故障,仅修复该分区即可
   (4) '均衡I/O'     : 将不同的分区放置不同的磁盘,以均衡 I/O,改善整个系统性能

   缺点:
   (1) 已经存在的表无法直接转化为分区表 -- 不过有很多间接方法,如:重定义表

4. 适用情况
   (1) 表的大小超过 2GB

1.1 思维导图

在这里插入图片描述

2 分类

2.1 传统表分区

2.1.1 范围分区 range

情况1:数值范围分区

create table pt_range_test1(
  pid   number(10),
  pname varchar2(30)
) partition by range(pid)(
  partition p1 values less than(1000) tablespace tetstbs1,
  partition p2 values less than(2000) tablespace tetstbs2,
  partition p3 values less than(maxvalue) tablespace tetstbs3
) enable row movement;

插入数据:

insert into pt_range_test1 (pid, pname) values (1, '瑶瑶');
insert into pt_range_test1 (pid, pname) values (1500, '倩倩');
insert into pt_range_test1 (pid, pname) values (null, '优优');
commit;

查询数据:

select * from user_tab_partitions t;

select 'P1' 分区名, t.* from pt_range_test1 partition (p1) t union all
select 'P2' 分区名, t.* from pt_range_test1 partition (p2) t union all
select 'P3' 分区名, t.* from pt_range_test1 partition (p3) t

在这里插入图片描述

情况2:时间范围分区(同理)

create table pt_range_test2(
  pid         number(10),
  pname       varchar2(30),
  create_date date
) partition by range(create_date)(
  partition p1 values less than(to_date('2020-01-01', 'YYYY-MM-DD')) tablespace tetstbs1,
  partition p2 values less than(to_date('2021-01-01', 'YYYY-MM-DD')) tablespace tetstbs2,
  partition p3 values less than(maxvalue) tablespace tetstbs3
) enable row movement;

2.1.2 列表分区 list

create table pt_list_test(
  pid   number(10),
  pname varchar2(30),
  sex   varchar2(10)
) partition by list(sex)(
  partition p1 values ('MAN', '男') tablespace tetstbs1,
  partition p2 values ('WOMAN', '女') tablespace tetstbs2,
  partition p3 values (default) tablespace tetstbs3
) enable row movement;

插入数据:

insert into pt_list_test (pid, pname, sex) values (1, '瑶瑶', '男');
insert into pt_list_test (pid, pname, sex) values (2, '倩倩', 'WOMAN');
insert into pt_list_test (pid, pname, sex) values (3, '优优', 'GOD');
commit;

查询数据:

select 'P1' 分区名, t.* from pt_list_test partition (p1) t union all
select 'P2' 分区名, t.* from pt_list_test partition (p2) t union all
select 'P3' 分区名, t.* from pt_list_test partition (p3) t

在这里插入图片描述

2.1.3 哈希分区 hash

create table pt_hash_test(
  pid   number(10),
  pname varchar2(30)
) partition by hash(pid)(
  partition p1 tablespace tetstbs1,
  partition p2 tablespace tetstbs2,
  partition p3 tablespace tetstbs3,
  partition p4 tablespace tetstbs4,
);

简写:

create table pt_hash_test2(
  pid   number(10),
  pname varchar2(30)
) partition by hash(pid) 
  partitions 4 store in (tetstbs1, tetstbs2, tetstbs3, tetstbs4);

2.1.4 复合分区 range + list or hash

情况1:range + list

create table pt_range_list_test(
   pid         number(10),
   pname       varchar2(30),
   sex         varchar2(10),
   create_date date
) partition by range(create_date) 
  subpartition by list(sex)(
    partition p1 values less than(to_date('2020-01-01', 'YYYY-MM-DD')) tablespace tetstbs1(
      subpartition sub1p1 values('MAN') tablespace tetstbs1,
      subpartition sub2p1 values('WOMAN') tablespace tetstbs1,
      subpartition sub3p1 values(default) tablespace tetstbs1
    ),
    partition p2 values less than(to_date('2021-01-01', 'YYYY-MM-DD')) tablespace tetstbs2(
      subpartition sub1p2 values('MAN') tablespace tetstbs2,
      subpartition sub2p2 values('WOMAN') tablespace tetstbs2,
      subpartition sub3p2 values(default) tablespace tetstbs2
    ),
    partition p3 values less than(maxvalue) tablespace tetstbs3(
      subpartition sub1p3 values('MAN') tablespace tetstbs3,
      subpartition sub2p3 values('WOMAN') tablespace tetstbs3,
      subpartition sub3p3 values(default) tablespace tetstbs3
    )
  ) enable row movement;

情况1:range + hash

create table pt_range_hash_test(
   pid         number(10),
   pname       varchar2(30),
   sex         varchar2(10),
   create_date date
) partition by range(create_date) 
  subpartition by hash(pid) subpartitions 4 store in (tetstbs1, tetstbs2, tetstbs3, tetstbs4)(
     partition p1 values less than(to_date('2020-01-01', 'YYYY-MM-DD')) tablespace tetstbs1,
     partition p2 values less than(to_date('2021-01-01', 'YYYY-MM-DD')) tablespace tetstbs2,
     partition p3 values less than(to_date('2022-01-01', 'YYYY-MM-DD')) tablespace tetstbs3,
     partition p4 values less than(maxvalue) tablespace tetstbs4
  ) enable row movement;

2.2 11g 新特性分区

2.1.1 引用分区 reference

  • 外键列必须 not null
-- 父表
create table pt_reference_father_test(
   pid         number(10),
   pname       varchar2(30),
   create_date date,
   constraint pk_ptrft_pid primary key(pid)
) partition by range(create_date)(
    partition p1 values less than(to_date('2020-01-01', 'YYYY-MM-DD')) tablespace tetstbs1,
    partition p2 values less than(to_date('2021-01-01', 'YYYY-MM-DD')) tablespace tetstbs2,
    partition p3 values less than(maxvalue) tablespace tetstbs3
  ) enable row movement;


-- 子表
create table pt_reference_son_test(
   pid     number(10) not null, -- 必须 not null,否则报错
   item_id number(10),
   constraint pk_ptrst_item_id primary key(item_id),
   constraint fk_ptrst_pid foreign key(pid)
   references pt_reference_father_test(pid)       
) partition by reference(fk_ptrst_pid)
  enable row movement;

2.1.2 间隔分区 interval

  • 必须有个初始分区,且无法删除(除非直接删除表)
-- 初始时间范围分区 2020-01-01
-- 之后数据每间隔 1 年,新建一个分区
create table pt_interval_test(
  pid         number(10),
  pname       varchar2(30),
  create_date date
) partition by range(create_date) 
  interval(numtoyminterval(1, 'YEAR'))(
     partition p1 values less than(to_date('2020-01-01', 'YYYY-MM-DD')) tablespace tetstbs1
  );

分别插入数据,观察变化:

insert into pt_interval_test(pid, pname, create_date) values(1, '瑶瑶', to_date('2019-01-01', 'YYYY-MM-DD'));

insert into pt_interval_test(pid, pname, create_date) values(2, '倩倩', to_date('2020-01-01', 'YYYY-MM-DD'));

select * from user_tab_partitions t where t.table_name = upper('pt_interval_test');

在这里插入图片描述

2.1.3 虚拟列分区 virtual

  • 将分区建立在某个虚拟列上(函数或表达式 的计算结果上)
create table pt_virtual_test(
  pid         number(10),
  pname       varchar2(30),
  create_date date,
  create_quarterly as (to_char(create_date,'D')) virtual
) partition by list(create_quarterly)(
    partition p1 values(1) tablespace tetstbs1,
    partition p2 values(2) tablespace tetstbs2,
    partition p3 values(3) tablespace tetstbs3,
    partition p4 values(4) tablespace tetstbs4,
    partition p5 values(default) tablespace tetstbs4
  );

2.1.4 系统分区 system

  • 不能指定分区列
create table pt_system_test(
  pid   number(10),
  pname varchar2(30)
) partition by system(
    partition p1 tablespace tetstbs1,
    partition p2 tablespace tetstbs2,
    partition p3 tablespace tetstbs3
  );

3 管理

3.1 表分区

1. 查询: 
   (1) select * from user_tab_partitions t;

2. 添加: 
   (1) alter table <table_name> add partition <partition_name> values less than(to_date('2020-02-02', 'YYYY-MM-DD'));
   (2) alter table <table_name> add partition <partition_name> values less than(1000);

3. 删除: (请注意:无法删除分区表唯一的分区,除非删除表)
   (1) alter table <table_name> drop partition <partition_name>;
   (2) alter table <table_name> drop subpartition <subpartition_name>;

4. 截断分区('清空某个分区的数据'(1) alter table <table_name> truncate partition <partition_name>;
   (2) alter table <table_name> truncate subpartition <subpartition_name>;

5. 拆分分区('拆分后,原来分区不再存在'(1) alter table <table_name> sblit partition <p12> at(to_date('2020-01-01', 'YYYY-MM-DD')) into (partition p1, partition p2);
   
6. 合并分区
   (1) alter table <table_name> merge partitions <p1>, <p2> into partition <p12>;

7. 重命名分区
   (1) alter table <table_name> rename partition <pold> to <pnew>

3.2 表空间

1. 查询
   (1) select * from user_tablespaces t;
   
2. 创建 -- 创建表空间时,可选项有很多,此处仅列出必选项
   create tablespace "tbs"
   datafile 'D:\oracle\tbs_01.dbf'
   size 10m;

3. 删除
   (1) 仅删除表空间:drop tablespace tbs;
   (2) 删除表空间和数据文件:drop tablespace tbs including contents and datafiles;

猜你喜欢

转载自blog.csdn.net/qq_34745941/article/details/109027781