基於Oracle11.2.04
分區表的概念
當表中的數據量不斷增大,查詢數據的速度就會變慢,應用程序的性能就會下降,這時就應該考慮對錶進行分區。表進行分區後,邏輯上仍然是一張完整的表,只是將表中的數據在物理上存放到多個表空間(物理文件上),這樣查詢數據時,不至於每次都掃描整張表。
分區表的優點
- 改善查詢性能:對分區對象的查詢可以公搜索自己關心的分區,提高檢索速度。
- 增強可用性:如果表的某個分區出現故障,表在其他分區的數據仍然可用。
- 維護方便:如果表的某個分區出現故障,需要修復數據,只修復該分區即可。
- 均衡I/O:可以把不同的分區映射到磁盤以平衡I/O,改善整個系統性能。
什麼時候需要分區
官網的建議:
- Tables greater than 2GB should always be considered for partitioning.
- tables containing historical data, in which new data is added into the newest partition. A typical example is a historical table where only the current month’s data is updatable and the other 11 months ar read only.
分區表的種類
範圍分區
Range分區就是以列的值的範圍來做爲分區的劃分條件,將記錄放到列值所在的range分區中,因此在創建的時候,你需要指定基於的列,以及分區的範圍值,如果某些記錄暫時無法預測範圍,可以創建maxvalue分區,所有不在指定範圍內的記錄都會被存儲到maxvalue所在分區中,並且支持多列做爲依賴列。
語法:
- column: 分區依賴列(如果是多個,以逗號分隔)
- partition: 分區名稱
- values less than:後跟分區範圍值(如果依賴列有多個,範圍對應的值也有多個,中間以逗號分隔)
- tablespace_clause:分區的存儲屬性,例如果所在表空間等屬性(可爲空), 默認繼承基表所在表空間的屬性。
e.g.
create table table_name(
...
)
partition by range(column_name)
(
partition p1 values less than(values1),
partition p2 values less than(values2),
partition other values less than(maxvalue)
);
interval partition
interval partition的限制
- intervall partition的限制包括“Restrictions on Parrtition in Gennerall " 和" Restrictions on Range Parrtitioning"。
- 只能指定一個partitioning key列,而且這個列只能是NUMBER,DATE, FLOAT和TIMESTAMP數據類型。
- 必須指定至少一個range分區
- 當有記錄插入時,系統根據需要自動創建新的分區和本地索引
- 。。。
e.g. 按月自動創建分區。
create table table_name(
...
) tablespace tablespace_name
partition by range(partitions_field) interval(numtoyminterval(1, 'month'))
store in (tablespace_name)
(
partition partition_name_01 values less than(TIMESTAMP'2018-01-01 00:00:00') tablespace tablespace_name
)
interval分區和range分區的轉換
-
range分區轉換成interval分區
alter table table_name set interval(numtoyminterval(1, 'year'));
-
interval分區轉換成range分區
alter table table_name set interval();
允許分區表的分區鍵是可更新
指當分區列的值更新後,就會把行數據從指定分區中delete掉,然後插入新的分區表。
alter table table_name enable row movement;
Hash分區
根據字段的hash值進行均勻分區,儘可能的實現各分區所散列的數據相等。通常是那些無法有效劃分範圍的表,使用hash分區,這樣對於提高性能還是會有一定的幫助。列所在分區是依賴分區列的hash值自動分配,因此你並不能控制也不知道哪條記錄會被放到哪個分區中,hash分區也可以支持多個依賴列。
Hash分區定義規則:
在定義Hash分區時,其分區數量應爲2的N次方。
對於Hash分區,如果更改分區的數量,將導致所有數據在分區間的重新分佈。
e.g.
create table table_name(
...
)
partition by hash(column_name)
(
partition p1,
partition p2,
partition p3,
...
);
List分區
List分區與range分區和hash分區都有類似之處,該分區與range分區相似的是也需要你指定列的值,但你必須明確指定值,並不能指定範圍。與hash分區不同之處在於你能控制記錄存儲在哪個分區。但它的分區列只能有一個,不過它的單個分區對應的值可以是多個。你在分區時必須確定分區列可能存在的值,一旦插入的列值不在分區範圍內,則插入、更新就會失敗,因此通過建議使用List分區時,要創建一個default分區存儲那些不在指定範圍內的記錄,類似range分區中的maxvalue分區。
create table table_name(
...
)
partition by list(column)
(
partition value1 values('1'),
partition value2 values('2'),
...
)
組合分區
注意:對於同一張組合分區表而言,子分區的名字不能相同,即使不在相同的分區裏。
- 範圍-散列分區
e.g.
create table table_name(
...
)
partition by range(column1)
subpartition by hash(column2)
(
partition p1 values less than(oneValue)
(
subpartition sp1,
subpartition sp2,
...
),
partition p2 values less than(maxvalue)
(
subpartition sp3,
subpartition sp4,
...
)
);
2… 範圍-列表分區
e.g.
create table table_name(
...
)
partition by range(column2) subpartition by list(column3)
(
partition p1 values less than('value1')
(
subpartition one values('01', '11'),
subpartition two values('02', '22'),
...
),
partition p2 values less than('value2')
(
subpartition three values('03', '33'),
...
),
...
)
索引
分區索引分爲兩類,一類叫local,一類叫global。
全局索引
是在全局建立索引,這種方式和建立不建立分區一樣一般不使用。
還有一種就是自定義數據區間的索引,也叫做前綴索引,不過自定義區域值必須有maxvalue。
global自定義全局(前綴索引)索引方式方法:
create index index_namme on table(field) global
partition by range(field) (
partition parrtition_name1 values less than(values),
partition partition_name2 values less thhan(maxvalue)
)
global全局索引:
create index index_name on tablle(fiield) global;
Local索引
在每個分區建立索引。需要注意,在分區上建立的索引必須是分區字段。
create index index_name on table(field) local;
查看分區索引
select * from user_ind_partitions;
分區表操作
查詢分區表
修改分區信息狀態後需要重新收集分區表的統計信息。
- 查詢分區表
selecct table_name, partitioning_type, partition_count, status
from dba_part_tables
where table_name = 'table_name'
- 查詢單獨分區表
select * from table_name partition(partition_name)
- 查詢分表各分區的條件以及數據庫分佈情況
sellect a.table_name, partitioning_type, partition_name, high_value, num_rows
from user_part_tables a, user_tab_parrtitions b
where a.table_name = b.table_name
- 收集分區表的統計信息
analyze table test_range_partition coompute statistics;
創建新分區
注意:當分區表存在默認條件分區,如:range分區表的maxvalue分區,list分區表的default分區,此時增加分區操作會報錯。
可以刪除原默認條件分區,待增加分區後,再重新添加默認條件分區. 不過默認條件的分區的刪除,其數據不會重分佈到其他分區,而是刪除數據。因此在生產環境使用需要慎重。
或者使用拆分分區(split)的方式。
刪除分區
對於分區的刪除操作,需要注意,在刪除分區後,分區所記錄的數據,不會重新分配到其他分區中,而是被刪除。慎用。
alter table table_name drop partition partition_name;
移動分區
移動分區所在的表空間,不過對於組合分區,無法直接移動分區。需要先修改子分區的所在表空間,然後再修改分區的分區屬性。
alter table table_name move partition partition tablespace tablespace_name;
截斷分區
截斷分區維護操作,相對於傳統的delete操作,刪除數據的效率會更高。而且會降低高水位線。
alter table table_name truncate partition partition_name;
拆分分區
在目標分區被拆分後,被拆分的分區會按照拆分規則,將數據進行重分佈。
alter table table_name split partition partition_name at (values) into (
partition partition_name,
...);
???
合併分區
合併分區操作,主要是將不同的分區,通過分區的合併,進行整合。
需要注意:
- 對於List分區,合併的分區無限制要求。
- 對於Range分區,合併的分區必須相臨。
- 對於Hash分區,無法進行合併操作。
此外,對於Range分區,下限由邊界值較低的分區決定,上限值由邊界值較高的分區決定。
alter table table_name merget partitions partition_name1, partition_name2 [,...] into partition_name_merge;
交換分區
交換分區技術,主要是將一個非分區表的數據同一個分區表的一個分區進行數據交換。支持雙向交換,既可以從分區表的分區中遷移到非分區表,也可以從非分區表遷移到分區表的分區中。
原則上,非分區表的結構、數據分佈等,要符合分區表的目標分區的定義規則。解決辦法是通過without validation子句,可以避免數據校驗,而交換成功。但會存在與分區規則相悖的數據,因此在生產環境使用需要慎重。
技術方案擴展思路:若打算採用交換分區的方法,以實現非分區表到分區表的轉換,可以採用先創建一個只有默認條件的單一分區的分區表,在分區交換數據後,根據實際需要,通過前面提到的“拆分分區”的方法進行分區操作。
alter table table_name_has_partitions exchange partition partition_name with table table_name_no_partitions;
收縮分區維護操作(colaesce)
收縮分區維護操作,僅僅可以在hash分區以及組合分區的hash子分區上進行使用。通過使用收縮分區技術,可以收縮當前hash分區的分區數量。對於hash分區的數據,在收縮過程中,oracle會自動完成數據在分區間的重分佈。
alter table table_name coalesce partition;
需要注意:當hash分區中只有一個分區時,此時無法進行收縮操作。
分割分區
附錄
顯示分區表信息
- 顯示數據庫所有分區表的信息:DBA_PART_TABLES
- 顯示當前用戶可訪問的所有分區表信息:ALL_PART_TABLES
- 顯示當前用戶所有分區表的信息:USER_PART_TABLES
顯示錶分區信息
- 顯示數據庫所有分區表的詳細分區信息:DBA_TAB_PARTITIONS
- 顯示當前用戶可訪問的所有分區表的詳細分區信息:ALL_TAB_PARTITIONS
- 顯示當前用戶所有分區表的詳細分區信息:USER_TAB_PARTITIONS
顯示子分區信息
- 顯示數據庫所有組合子分區表的子分區信息:DBA_TAB_SUBPARTITIONS
- 顯示當前用戶可訪問的所有組合分區表的子分區信息:ALL_TAB_SUBPARTITIONS
- 顯示當前用戶所有組合分區表的子分區信息: USER_TAB_SUBPARTITIONS
顯示分區列
- 顯示數據庫所有分區表的分區列信息:DBA_PART_KEY_SOLUMNS
- 顯示當前用戶可訪問的所有分區表的分區列信息:ALL_PART_KEY_SOLUMNS
- 顯示當前用戶所有分區表的分區列信息:USER_PART_KEY_COLUMNS
顯示子分區信息
- 顯示數據庫所有組合分區表的子分區信息:DBA_TAB_SUBPARTITIONS
- 顯示當前用戶可訪問的所有組合分區表的子分區信息:ALL_TAB_SUBPARTITIONS
- 顯示當前用戶所有組合分區表的子分區的信息:USER_TAB_SUBPARTITIONS
顯示分區列
- 顯示數據庫所有分區表的分區列信息:DBA_PART_KEY_COLUMNS
- 顯示當前用戶可訪問的所有分區表的分區列信息:ALL_PART_KEY_COLUMNS
- 顯示當前用戶所有分區表的分區列信息:USER_PART_KEY_COLUMNS
顯示子分區列
- 顯示數據庫所有分區表的子分區列信息:DBA_SUBPART_KEY_COLUMNS
- 顯示當前用戶可訪問的所有分區表的子分區列信息:ALL_SUBPART_KEY_COLUMNS
- 顯示當前用戶所有分區表的子分區列信息:USER_SUBPART_KEY_COLUMNS