前提:
查詢分區:Select *From user_extents WHERE partition_name='分區名';
1)創建表空間
create tablespace HRPM0
datafile '/oradata/misdb/HRPM0.DBF' size 5m autoextend on next 10m maxsize unlimited
2)刪除表空間(同時把數據文件也刪除)
DROP TABLESPACE data01 INCLUDING CONTENTS AND DATAFILES;
如果不想刪除數據文件:
Drop tablespace tablespace_name;
3) 修改表空間大小
alter database datafile '/path/NADDate05.dbf' resize 100M
4)添加數據文件(在建立表空間時,若是約束了表空間的大小,那麼一段時間後,這個表空間就會被裝滿,無法再添加其他對象。則需要給表空間添加數據文件):
Alter tablespace tablespace_name add datafile’ '/path/NADDate06.dbf’ size 100M;
4) 備註:
4.1).--.禁止undo tablespace自動增長
alter database datafile 'full_path\undotbs01.dbf' autoextend off;
4.2).-- 創建一個新的小空間的undo tablespace
create undo tablespace undotBS2 datafile 'full_path\UNDOTBS02.DBF' size 100m;
4.3).-- 設置新的表空間爲系統undo_tablespace
alter system set undo_tablespace=undotBS2;
4.4).-- Drop 舊的表空間
drop tablespace undotbs1 including contents;
4.5).--查看所有表空間的情況
select * from dba_tablespaces
5)查到一個最好用的表:dict
5.1)select *from dict where table_name like '%PART%'
5.2)ALL_TAB_PARTITIONS:可以查出表所對應的分區內容;
5.3)dab_tab_partitons :與上2);
5.4)dba_ind_partitons:查詢分區的索引;
5.5)子分區也是一樣的(dba_tab_subpartitons,dba_ind_partitons)
一、使用分區的優點:
1、增強可用性:如果表的某個分區出現故障,表在其他分區的數據仍然可用;
2、維護方便:如果表的某個分區出現故障,需要修復數據,只修復該分區即可;
3、均衡I/O:可以把不同的分區映射到磁盤以平衡I/O,改善整個系統性能;
4、改善查詢性能:對分區對象的查詢可以僅搜索自己關心的分區,提高檢索速度。
二、Oracle數據庫提供對錶或索引的分區方法有幾種(收集到四種):
1、範圍分區
2、列表分區
3、Hash分區(散列分區)
4、複合分區
三、詳描述分區實例:
1)下面將以實例的方式分別對這三種分區方法來說明分區表的使用。爲了測試方便,我們先建三個表空間。
create tablespace dinya_space01 datafile 'C:\表空間\dinya01.dbf' size 5M;
create tablespace dinya_space02 datafile 'C:\表空間\dinya02.dbf'SIZE 5M;
create tablespace dinya_space03 datafile 'C:\表空間\dinya03.dbf' SIZE 5M;
select * from user_tablespaces
1.1)範圍分區
範圍分區就是對數據表中的某個值的範圍進行分區,根據某個值的範圍,決定將該數據存儲在哪個分區上。如根據序號分區,根據業務記錄的創建日期進行分區等。
需求描述:有一個物料交易表,表名:material_transactions。該表將來可能有千萬級的數據記錄數。要求在建該表的時候使用分區表。這時候我們可以使用序號分區三個區,每個區中預計存儲三千萬的數據,也可以使用日期分區,如每五年的數據存儲在一個分區上。
根據交易記錄的序號分區建表:----爲了測試需要做以下修改;
create table dinya_test
(
transaction_id number primary key,
item_id number(8) not null,
item_description varchar2(300),
transaction_date date not null
)
partition by range (transaction_id)
(
partition part_01 values less than(2) tablespace dinya_space01,-----2條以下的交易在此分區上:part_01
partition part_02 values less than(3) tablespace dinya_space02,-----等於+大於2而小於3的交易在此分區:part_02
partition part_03 values less than(maxvalue) tablespace dinya_space03----大於3的交易在此分區:part_03
根據交易日期分區建表:
SQL> create table dinya_test
(
transaction_id number primary key,
item_id number(8) not null,
item_description varchar2(300),
transaction_date date not null
)
partition by range (transaction_date)
(
partition part_01 values less than(to_date('2006-01-01','yyyy-mm-dd')) tablespace dinya_space01,
partition part_02 values less than(to_date('2010-01-01','yyyy-mm-dd')) tablespace dinya_space02,
partition part_03 values less than(maxvalue) tablespace dinya_space03
);
這樣我們就分別建了以交易序號和交易日期來分區的分區表。每次插入數據的時候,系統將根據指定的字段的值來自動將記錄存儲到制定的分區(表空間)中。
當然,我們還可以根據需求,使用兩個字段的範圍分佈來分區,如partition by range ( transaction_id ,transaction_date),分區條件中的值也做相應的改變,請讀者自行測試。
1.2) 範圍分區創建成功之後的相關操作測試;
a)向表添加測試數據:
insert into dinya_test values(1,12,'BOOKS',sysdate);
insert into dinya_test values(2,12, 'BOOKS',sysdate+30);
insert into dinya_test values(3,12, 'BOOKS',to_date('2006-05-30','yyyy-mm-dd'));
insert into dinya_test values(4,12, 'BOOKS',to_date('2007-06-23','yyyy-mm-dd'));
insert into dinya_test values(5,12, 'BOOKS',to_date('2011-02-26','yyyy-mm-dd'));
insert into dinya_test values(6,12, 'BOOKS',to_date('2011-04-30','yyyy-mm-dd'));
b)查詢
b.1)如果查詢全表數據
select * from dinya_test;
select * from dinya_test partition(part_01);
select * from dinya_test partition(part_02);
select * from dinya_test partition(part_03);
update dinya_test partition(part_01) t set t.item_description='DESK' where t.transaction_id=1;
select * from dinya_test partition(part_01);BOOKS->DESK(發生變化)
select * from dinya_test(此結果就不用查看了,肯定變了);
---刪除part_03分區中transaction_id=4的記錄:
delete from dinya_test partition(part_03) t where t.transaction_id=4;
select * from dinya_test partition(part_03)
c)索引的創建:
c.1)局部索引的創建:
create index dinya_idx_t on dinya_test(item_id)
local
(
partition idx_1 tablespace dinya_space01,---分區名爲:idx_1
partition idx_2 tablespace dinya_space02, ---分區名爲:idx_2
partition idx_3 tablespace dinya_space03---分區名爲:idx_3
);
注:
select *from ALL_TAB_PARTITIONS where table_name ='DINYA_TEST'
select *From dba_ind_partitions where partition_name='IDX_1'
c.2)全局索引的創建:
全局索引建立時global 子句允許指定索引的範圍值,這個範圍值爲索引字段的範圍值:
create index dinya_idx_t on dinya_test(item_id)
global partition by range(item_id)
(
partition idx_1 values less than (1000) tablespace dinya_space01,
partition idx_2 values less than (10000) tablespace dinya_space02,
partition idx_3 values less than (maxvalue) tablespace dinya_space03
);----PL/SQL末測試[參照以上local];
整個表創建索引:
Create index dinya_idx_t on dinya_test(item_id);
備註: select *from all_indexes(dba_indexes、all_ind_columns 、user_ind_columns 、 dba_ind_columns)
1.3) Hash分區(散列分區)
散列分區爲通過指定分區編號來均勻分佈數據的一種分區類型,因爲通過在I/O設備上進行散列分區,使得這些分區大小一致。如將物料交易表的數據根據交易ID散列地存放在指定的三個表空間中:
create table dinya_test
(
transaction_id number primary key,
item_id number(8) not null,
item_description varchar2(300),
transaction_date date
)
partition by hash(transaction_id)
(
partition part_01 tablespace dinya_space01,
partition part_02 tablespace dinya_space02,
partition part_03 tablespace dinya_space03
);
建表成功,此時插入數據,系統將按transaction_id將記錄散列地插入三個分區中,這裏也就是三個不同的表空間中。
1.4) 列表分區:該分區的特點是某列的值只有幾個,基於這樣的特點我們可以採用列表分區。
示例1:
CREATE TABLE PROBLEM_TICKETS
(
PROBLEM_ID NUMBER(7) NOT NULL PRIMARY KEY,
DESCRIPTION VARCHAR2(2000),
CUSTOMER_ID NUMBER(7) NOT NULL,
DATE_ENTERED DATE NOT NULL,
STATUS VARCHAR2(20)
)
PARTITION BY LIST (STATUS)
(
PARTITION PROB_ACTIVE VALUES ('ACTIVE') TABLESPACE PROB_TS01,
PARTITION PROB_INACTIVE VALUES ('INACTIVE') TABLESPACE PROB_TS02
)
備註:active和inactive是列status的值!謹記與range和hash分區的區別;
1.4.1)測試如下:
insert into PROBLEM_TICKETS values(1,'BOOKS',1,sysdate,'ACTIVE');
insert into PROBLEM_TICKETS values(2,'son',2,sysdate+30,'INACTIVE');
insert into PROBLEM_TICKETS values(3,'son',3,to_date('2006-05-30','yyyy-mm-dd'),'INACTIVE');
insert into PROBLEM_TICKETS values(4,'BOOKS',4,to_date('2007-06-23','yyyy-mm-dd'),'INACTIVE');
insert into PROBLEM_TICKETS values(5,'old',5,to_date('2011-02-26','yyyy-mm-dd'),'ACTIVE');
insert intoPROBLEM_TICKETSvalues(6,'test',6,to_date('2011-04-30','yyyy-mm-dd'),'INACTIVE');
select * from PROBLEM_TICKETS
1.4.2)
select * from PROBLEM_TICKETS partition(PROB_ACTIVE)
1.4.2)
select * from PROBLEM_TICKETS partition(PROB_INACTIVE)
在測試中遇到這樣的情況。如果表創建了分區,如果要刪除數據文件(表空間文件),則要先刪除分區,然後才能刪除數據文件(但是在刪除數據文件時,必須要保留一個分區才能最終刪除數據文件>表空間文件,)
當然,也可以直接就刪除表也行,剛所有的全刪除,但是表空間文件還在!
1.5) 複合分區
有時候我們需要根據範圍分區後,每個分區內的數據再散列地分佈在幾個表空間中,這樣我們就要使用複合分區。複合分區是先使用範圍分區,然後在每個分區內再使用散列分區的一種分區方法,如將物料交易的記錄按時間分區,然後每個分區中的數據分三個子分區,將數據散列地存儲在三個指定的表空間中:
create table dinya_test
(
transaction_id number primary key,
item_id number(8) not null,
item_description varchar2(300),
transaction_date date
)
partition by range(transaction_date)subpartition by hash(transaction_id)
subpartitions 3 store in (dinya_space07,dinya_space08,dinya_space09)
(
partition part_07 values less than(to_date('2006-01-01','yyyy-mm-dd')),
partition part_08 values less than(to_date('2010-01-01','yyyy-mm-dd')),
partition part_09 values less than(maxvalue)
);
---測試如下:
select *From user_tab_partitions where table_name=upper('dinya_test')
selec *From user_tab_subpartitions where table_name=upper('dinya_test')
插入如下數據:
insert into dinya_test values(1,12,'BOOKS',sysdate);
insert into dinya_test values(2,12, 'BOOKS',sysdate+30);
insert into dinya_test values(3,12, 'BOOKS',to_date('2006-05-30','yyyy-mm-dd'));
insert into dinya_test values(7,12, 'BOOKS',to_date('2005-05-30','yyyy-mm-dd'));
insert into dinya_test values(4,12, 'BOOKS',to_date('2007-06-23','yyyy-mm-dd'));
insert into dinya_test values(5,12, 'BOOKS',to_date('2011-02-26','yyyy-mm-dd'));
insert into dinya_test values(6,12, 'BOOKS',to_date('2011-04-30','yyyy-mm-dd'));
select *From dinya_test;
select *From dinya_test partition(part_07);
select *From dinya_test partition(part_09);
參照下圖,按所顯的子分區名,看能否查出數據:
select*Fromuser_tab_subpartitions where table_name=upper('dinya_test');
select *From dinya_test subpartition(SYS_SUBP62);
備註: 該例中,先是根據交易日期進行範圍分區,然後根據交易的ID將記錄散列地存儲在三個表空間中。
1.6) 複合範圍列表分區:這種分區是基於範圍分區和列表分區,表首先按某列進行範圍分區,然後再按某列進行列表分區,分區之中的分區被稱爲子分區。
示例1:
Create table sales
(
Product_id varchar2(5),
Sales_date date,
Sales_cost number(10),
Status varchar2(20)
)
Partition by range(Sales_cost)
Subpartition by list(status)
(
Partition p1 values less than (1) tablespace dinya_space01
(
Subpartition p1sub1 values('ACTIVE') tablespace dinya_space03,
Subpartition p1sub2 values('INACTIVE') tablespace dinya_space04
),
Partition p2 values less than (3) tablespace dinya_space02
(
Subpartition p1sub3 values('ACTIVE') tablespace dinya_space05,
Subpartition p1sub4 values('INACTIVE') tablespace dinya_space06
)
)測試如下:
insert into sales values(1,sysdate,0.1,'ACTIVE');
insert into sales values(2,sysdate+30,1,'INACTIVE');
insert into sales
values(3,to_date('2006-05-30','yyyy-mm-dd'),2,'INACTIVE');
select *From sales:
Select *from sales partition(p2)
SELECT * FROM SALES SUBPARTITION(p1sub4)
SELECT * FROM SALES SUBPARTITION(p1sub3)
沒有數據!!
select *From dba_tab_subpartitions where table_name='SALES'
有關表分區的一些維護性操作:
一、添加分區
以下代碼給SALES表添加了一個P3分區
ALTER TABLE SALES ADD PARTITION P3 VALUES LESS THAN(TO_DATE('2003-06-01','YYYY-MM-DD'));
注意:以上添加的分區界限應該高於最後一個分區界限。
以下代碼給SALES表的P3分區添加了一個P3SUB1子分區
ALTER TABLE SALES MODIFY PARTITION P3 ADD SUBPARTITION P3SUB1 VALUES('COMPLETE');
二、刪除分區
以下代碼刪除了P3表分區:
ALTER TABLE SALES DROP PARTITION P3;
在測試中遇到這樣的情況。如果表創建了分區,如果要刪除數據文件(表空間文件),則要先刪除分區,然後才能刪除數據文件(但是在刪除數據文件時,必須要保留一個分區才能最終刪除數據文件>表空間文件,)
當然,也可以直接就刪除表也行,剛所有的全刪除,但是表空間文件還在!
在以下代碼刪除了P4SUB1子分區:
ALTER TABLE SALES DROP SUBPARTITION P4SUB1;
注意:如果刪除的分區是表中唯一的分區,那麼此分區將不能被刪除,要想刪除此分區,必須刪除表。
三、截斷分區
截斷某個分區是指刪除某個分區中的數據,並不會刪除分區,也不會刪除其它分區中的數據。當表中即使只有一個分區時,也可以截斷該分區。通過以下代碼截斷分區:
ALTER TABLE SALES TRUNCATE PARTITION P2;
通過以下代碼截斷子分區:
ALTER TABLE SALES TRUNCATE SUBPARTITION P2SUB2;
四、合併分區
合併分區是將相鄰的分區合併成一個分區,結果分區將採用較高分區的界限,值得注意的是,不能將分區合併到界限較低的分區。以下代碼實現了P1 P2分區的合併:
ALTER TABLE SALES MERGE PARTITIONS P1,P2 INTO PARTITION P2;
五、拆分分區
拆分分區將一個分區拆分兩個新分區,拆分後原來分區不再存在。注意不能對HASH類型的分區進行拆分。
ALTER TABLE SALES SBLIT PARTITION P2 AT(TO_DATE('2003-02-01','YYYY-MM-DD'))
INTO (PARTITION P21,PARTITION P22);
六、接合分區(coalesca)
結合分區是將散列分區中的數據接合到其它分區中,當散列分區中的數據比較大時,可以增加散列分區,然後進行接合,值得注意的是,接合分區只能用於散列分區中。通過以下代碼進行接合分區:
ALTER TABLE SALES COALESCA PARTITION;
七、重命名錶分區
以下代碼將P21更改爲P2
ALTER TABLE SALES RENAME PARTITION P21 TO P2;
九、跨分區查詢
select sum( *) from (
(select count(*) cn from t_table_SS PARTITION (P200709_1)
union all
select count(*) cn from t_table_SS PARTITION (P200709_2));
十、查詢表上有多少分區
SELECT * FROM useR_TAB_PARTITIONS WHERE TABLE_NAME='tableName'
--顯示數據庫所有分區表的信息:
select * from DBA_PART_TABLES where table_name=upper('dinya_test')
--顯示當前用戶可訪問的所有分區表信息:
select * from ALL_PART_TABLES
同上圖
--顯示當前用戶所有分區表的信息:
select * from USER_PART_TABLES
同上圖
--顯示錶分區信息 顯示數據庫所有分區表的詳細分區信息:
select * from DBA_TAB_PARTITIONS
--顯示當前用戶可訪問的所有分區表的詳細分區信息:
select * from ALL_TAB_PARTITIONS
--顯示當前用戶所有分區表的詳細分區信息:
select * from USER_TAB_PARTITIONS
--顯示子分區信息 顯示數據庫所有組合分區表的子分區信息:
select * from DBA_TAB_SUBPARTITIONS
--顯示當前用戶可訪問的所有組合分區表的子分區信息:
select * from ALL_TAB_SUBPARTITIONS
--顯示當前用戶所有組合分區表的子分區信息:
select * from USER_TAB_SUBPARTITIONS
--顯示分區列 顯示數據庫所有分區表的分區列信息:
select * from DBA_PART_KEY_COLUMNS
--顯示當前用戶可訪問的所有分區表的分區列信息:
select * from ALL_PART_KEY_COLUMNS
--顯示當前用戶所有分區表的分區列信息:
select * from USER_PART_KEY_COLUMNS
--顯示子分區列 顯示數據庫所有分區表的子分區列信息:
select * from DBA_SUBPART_KEY_COLUMNS
--顯示當前用戶可訪問的所有分區表的子分區列信息:
select * from ALL_SUBPART_KEY_COLUMNS
--顯示當前用戶所有分區表的子分區列信息:
select * from USER_SUBPART_KEY_COLUMNS
--怎樣查詢出oracle數據庫中所有的的分區表
select * from user_tables a where a.partitioned='YES'
--刪除一個表的數據是
truncate table table_name;
--刪除分區表一個分區的數據是
alter table table_name truncate partition p5;
注:分區根據具體情況選擇。
表分區有以下優點:
1、數據查詢:數據被存儲到多個文件上,減少了I/O負載,查詢速度提高。
2、數據修剪:保存歷史數據非常的理想。
3、備份:將大表的數據分成多個文件,方便備份和恢復。
4、並行性:可以同時向表中進行DML操作,並行性性能提高。
================================================
索引:
1、一般索引:
create index index_name on table(col_name);
2、Oracle 分區索引詳解
語法:Table Index
CREATE [UNIQUE|BITMAP] INDEX [schema.]index_name
ON [schema.]table_name [tbl_alias]
(col [ASC | DESC]) index_clause index_attribs
index_clauses:
分以下兩種情況
1. Local Index
就是索引信息的存放位置依賴於父表的Partition信息,換句話說創建這樣的索引必須保證父表是Partition
1.1 索引信息存放在父表的分區所在的表空間。但是僅可以創建在父表爲HashTable或者composite分區表的。
LOCAL STORE IN (tablespace)
1.2 僅可以創建在父表爲HashTable或者composite分區表的。並且指定的分區數目要與父表的分區數目要一致
LOCAL STORE IN (tablespace) (PARTITION [partition [LOGGING|NOLOGGING] [TABLESPACE {tablespace|DEFAULT}] [PCTFREE int] [PCTUSED int] [INITRANS int] [MAXTRANS int] [STORAGE storage_clause] [STORE IN {tablespace_name|DEFAULT] [SUBPARTITION [subpartition [TABLESPACE tablespace]]]])
1.3 索引信息存放在父表的分區所在的表空間,這種語法最簡單,也是最常用的分區索引創建方式。
Local
1.4 並且指定的Partition 數目要與父表的Partition要一致
LOCAL (PARTITION [partition
[LOGGING|NOLOGGING]
[TABLESPACE {tablespace|DEFAULT}]
[PCTFREE int]
[PCTUSED int]
[INITRANS int]
[MAXTRANS int]
[STORAGE storage_clause]
[STORE IN {tablespace_name|DEFAULT]
[SUBPARTITION [subpartition [TABLESPACE tablespace]]]])
Global Index
索引信息的存放位置與父表的Partition信息完全不相干。甚至父表是不是分區表都無所謂的。語法如下:
GLOBAL PARTITION BY RANGE (col_list)
( PARTITION partition VALUES LESS THAN (value_list)
[LOGGING|NOLOGGING]
[TABLESPACE {tablespace|DEFAULT}]
[PCTFREE int]
[PCTUSED int]
[INITRANS int]
[MAXTRANS int]
[STORAGE storage_clause] )
但是在這種情況下,如果父表是分區表,要刪除父表的一個分區都必須要更新Global Index ,否則索引信息不正確
ALTER TABLE TableName DROP PARTITION PartitionName Update Global Indexes
--查詢索引
select object_name,object_type,tablespace_name,sum(value)
from v$segment_statistics
where statistic_name IN ('physical reads','physical write','logical reads')and object_type='INDEX'
group by object_name,object_type,tablespace_name
order by 4 desc