1. 程式人生 > >oracle分區表

oracle分區表

速度 cor 根據 into prim 如果 ESS style p12

何時該分區

1. 大於2GB的表
2. 含有1000萬條記錄以上的表,表中含有的數據越多,SQL操作的執行速度就會越慢。
3. 將會含有大量數據的表。
4. 強行拆分後可利於並行操作的表。
5. 含有需要定期歸檔日誌或刪除部分的表

分區表的優點

1. 由於將數據分散到各個區中,減少損壞的可能性

2. 可以對單獨的分區進行備份和恢復

3. 可以將分區映射到不同的物理磁盤上,來分散I/O

4. 提高可管理性,可用性

分區表策略分類

範圍 --> 根據日期,數值或字符創建分區
列表 --> 根據列表值創建分區
散列 --> 在沒有明顯分區鍵的情況下,以均分方式創建分區


組合 --> 組合使用多種分區方式
間隔 --> 當新分區鍵值超出現存最大範圍時,通過自動分配新分區擴展範圍分區
引用 --> 根據父表列為子表創建分區
虛擬列分區 --> 在虛擬列上創建分區
系統 --> 根據插入數據的應用程序創建分區

常用的分區類型為:範圍、列表和散列

查詢數據量排行前十的表

一條可靠的原則就是大於2GB的表就可以應用分區功能。運行下面的查詢命令可以顯示數據庫中占用空間的排名情況:
select * from (
select owner,segment_name,segment_type,partition_name,sum(bytes)/1024/1024 meg_tot
from dba_segments group by owner,segment_name,segment_type,partition_name
order by sum(extents) desc)
where rownum <=10 

範圍分區

-- 創建一個普通表的語句
create table person1 (id int primary key, name varchar2(20), birth date);
-- 數據將會在同一個表空間同一個段內
insert into person1 values (1, ‘sss‘, sysdate);
 
-- 創建一個分區表
-- 這裏是按照生日進行範圍分區
-- 語句的基本格式就是在普通建表的語句上,增加 partition by 語句塊
create table person2 (name varchar2(20), birth date)
partition by range (birth)
(
  partition p1 values less than (to_date(‘19950101‘,‘yyyymmdd‘)),  -- ‘values less than‘
  partition p2 values less than (to_date(‘20000101‘,‘yyyymmdd‘)),
  partition p3 values less than (maxvalue)                         -- 默認分區
);
-- 插入,數據會根據分區的情況進入不同的分區內
insert into person2 values (‘張三‘, to_date(‘19940707‘));
insert into person2 values (‘李四‘, to_date(‘19980707‘));
insert into person2 values (‘王五‘, to_date(‘20040707‘));
-- 查詢表中所有數據
select * from person2;
-- 查詢特定分區上數據
select * from person2 partition (p3);
 
 
-- 可以為不同的分區指定不同的表空間
-- 沒有指定表空間的分區,使用用戶的默認表空間
-- 所以,一個表內的數據可以存在於不同表空間裏,也就是可以存放在不同數據文件中,不同磁盤上
-- 因此,分區表能增強數據的安全性
create table person3 (name varchar2(20), birth date)
partition by range (birth)
(
  partition p1 values less than (to_date(‘19950101‘,‘yyyymmdd‘)) tablespace system,
  partition p2 values less than (to_date(‘20000101‘,‘yyyymmdd‘)) tablespace sysaux,
  partition p3 values less than (maxvalue) tablespace users
);
 
 
-- 可以在其他類型上進行範圍分區
-- 也可以在多個字段上進行範圍分區
create table person4 (name varchar2(20), birth date, score number)
partition by range (birth, score)
(
  partition p1 values less than (to_date(‘19900101‘,‘yyyymmdd‘), 60),
  partition p2 values less than (to_date(‘19900101‘,‘yyyymmdd‘), 90),
  partition p3 values less than (to_date(‘19990101‘,‘yyyymmdd‘), 60),
  partition p4 values less than (to_date(‘19990101‘,‘yyyymmdd‘), 90),
  partition p5 values less than (maxvalue, maxvalue)
);

列表分區

-- 如果是生日的這樣的字段,數據是連續的,應該使用分為分區
create table person (name varchar2(20), birth date)
partition by range(birth)
(
  partition p1 values less than (to_date(‘19900101‘, ‘yyyymmdd‘)) tablespace users,
  partition p2 values less than (maxvalue)
);
insert into person values (‘aaa‘, to_date(‘19871212‘, ‘yyyymmdd‘));
select * from person partition (p1);
 
 
/* 
where birth between 1987 and 1990 
where sex in (‘男‘, ‘女‘)
*/
 
-- 但是像性別、民族等字段,更適合使用的是列表分區
-- 下面一個例子,使用性別作為分區字段,男的一個區,女的一個區
create table person2 (name varchar2(20), sex varchar(10))
partition by list (sex)
(
    partition p1 values (‘男‘),
    partition p2 values (‘女‘)
);
insert into person2 values (‘aaa‘, ‘男‘);
insert into person2 values (‘bbb‘, ‘女‘);
insert into person2 values (‘ccc‘, ‘未知‘);  -- 報錯
select * from person2 partition (p2);
 
-- 默認分區的寫法
create table person3 (name varchar2(20), sex varchar(10))
partition by list (sex)
(
    partition p1 values (‘男‘),
    partition p2 values (‘女‘),
    partition p3 values (default)
);
insert into person3 values (‘ccc‘, ‘未知‘);
select * from person3 partition (p3);
 
 
-- 可以為每個分區指定表空間
create table person3 (name varchar2(20), sex varchar(10))
partition by list (sex)
(
    partition p1 values (‘男‘) tablespace users,
    partition p2 values (‘女‘) tablespace system,
    partition p3 values (default)
);

哈希分區

-- 哈希分區
-- 主要用在一些比較離散,不好分類的數據上,比如產品名字
-- 讓 oracle 使用哈希算法自動計算數據的分區
 
-- 創建語句,非常簡單
create table person4 (name varchar2(20), sex varchar2(10))
partition by hash (name)
(
  partition p1,
  partition p2 tablespace users
);
insert into person4 values (‘aaa‘, ‘男‘);
insert into person4 values (‘收款‘, ‘男‘);
select * from person4 partition (p1);
 
-- 上面的語句可以進一步簡化為:
create table person5 (name varchar2(20), sex varchar2(10))
partition by hash (name)
partitions 5;
 
-- 為每個分區指定表空間
create table person6 (name varchar2(20), sex varchar2(10))
partition by hash (name)
partitions 3 store in (users, system, sysaux);

範圍與哈希組合

-- 先按照生日,將數據分為三個區
-- 然後在每個分區內,又按照哈希算法分成了三個區
-- 這樣就保證了每個分區內的數據盡量的少,而且分區進行平衡
create table person7 (name varchar2(20), birth date)
partition by range (birth)
subpartition by hash (name) subpartitions 3
(
  partition p1 values less than (to_date(‘19900101‘, ‘yyyymmdd‘)),
  partition p2 values less than (to_date(‘20000101‘, ‘yyyymmdd‘)),
  partition p3 values less than (maxvalue)
);

非分區表轉分區表

12c以前非分區表需要轉換為分區, 如果不停業務的話可以使用在線重定義,只有在表進行切換的時候會有短暫的鎖表。 12c 中alter table online clause 實現了表上現有的索引有效,又不停業務。

-- oracle 12c
create table person7 (name varchar2(20), birth date);
--將非分區表轉換為分區表,使用哈希
alter table person7 modify
partition by hash (name)
(
  partition ph1,
  partition ph2
) online
update indexes;

操作分區

-- 添加分區
alter table person add partition p9 values less than (MAXVALUE);
alter table person add partition p9 values (1, 2);   -- 針對 list 分區
alter table person add partition;                    -- 針對 hash 分區
 
-- 刪除分區
alter table person drop partition p3;
 
-- 刪除分區內數據
alter table person truncate partition p3;
 
-- 合並相鄰分區
alter table person merge partitions p2, p3 into partition p8;
 
-- 拆分分區
alter table person split partition p2 at (3000) into (partition p3, partition p14);     -- 範圍分區的拆分
alter table person split partition p2 values (1,2) into (partition p3, partition p4);   -- 列表分區的拆分
alter table person split partition p2 into (partition p3 values (1, 2), partition p4 values (3), partition p5);   -- 列表分區的拆分
 
-- 重命名分區
alter table person rename partition p2 to p12;

oracle分區表