聊聊Oracle聚簇Cluster(上)
Oracle資料表三種基本型別:堆表Heap Table、索引組織表IOT和聚簇表Cluster。在我們日常中,最常用也是適應性最好的一種資料表就是堆表Heap Table。一般在沒有特殊效能缺陷和特性要求的情況下,堆表是我們首先的選項。
IOT是一種融合資料到索引結構上的資料表型別。在筆者之前的文章中,詳細介紹了IOT的結構、特性和適應場景,同時也對段溢位Segment Overflow、邏輯Rowid和Secondary Index等概念進行過闡述。
本篇我們介紹一下聚簇。
1、概說聚簇Cluster
應該說,三種資料表型別中,我們最不常用的結構應該是聚簇。聚簇也是和其他兩種資料表差異最大的一種結構型別,最大的區別在於:聚簇是可以單獨存在的。
在Oracle儲存結構中,我們必須遵循兩個概念就是物件和段Segment。我們可以建立很多物件,比如資料表、索引、檢視,但是並不是每個物件都會“真刀真槍”的佔用儲存空間。Oracle空間分配是依據邏輯表空間、段物件、分割槽和塊。只有資料表、索引等物件,才是可以真正使用空間的,分配Segment的。
堆表和索引組織表雖然有差別,但是本質上是類似的。堆表中,索引和資料表是分別的資料段結構,索引段和資料表段保持一致性。而IOT實現了索引和資料表段的合一。資料表的所有內容,依據主鍵順序被儲存在IOT索引樹的葉子節點上。由於資料表內容的特殊性,比如欄位過大的情況,都是透過溢位段實現。
而Cluster完全不同,Cluster是一種單獨的段結構,或者筆者理解為單獨的段空間容器。在沒有資料表和索引的時候,Cluster段是可以單獨存在的。依據一定的規則,如連線鍵(Join Key),可以將多個資料表資料儲存在同一個段中。並且依據一定場景實現快速檢索連線。
我們為什麼使用Cluster資料表。最常見的解釋是減少關聯檢索時候進行IO的數量。傳統的資料表結構,兩個表連線,至少要進行兩次資料塊的檢索。而Cluster過程,由於都是儲存在一起(注意:相同Segment)。
Cluster進行使用的時候,有兩個型別進行選擇,分別為B樹Cluster和雜湊Hash Cluster。兩者既有相同的結構,又有細微的差異。
2、實驗環境介紹
我們選擇Oracle 11gR2進行實驗。
SQL> select * from v$version;
BANNER
-----------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - Production
PL/SQL Release 11.2.0.3.0 - Production
CORE 11.2.0.3.0 Production
TNS for Linux: Version 11.2.0.3.0 - Production
NLSRTL Version 11.2.0.3.0 – Production
建立專門的使用者進行實驗。
SQL> create user test identified by test default tablespace users;
User created
SQL> grant resource, connect to test;
Grant succeeded
SQL> grant create cluster to test;
Grant succeeded
SQL> grant select any table to test;
Grant succeeded
SQL> grant select any dictionary to test;
Grant succeeded
3、B樹Cluster實驗
透過一系列的實驗,我們來探討發現Cluster資料表的特性和使用。Oracle Cluster不是隨任何資料表物件建立,而是可以透過SQL語句create cluster來進行建立。
SQL> create cluster emp_dept (deptno number) size 600;
Cluster created
SQL> select cluster_name, tablespace_name, cluster_type, key_size from user_clusters;
CLUSTER_NAME TABLESPACE_NAME CLUSTER_TYPE KEY_SIZE
-------------------------- -------------------------- ------------ ----------
EMP_DEPT USERS INDEX 600
注意兩個問題,一個是建立cluster的過程中我們指定的size 600。這個是用於指定cluster鍵大致大小,指定之後,就可以實現空間的預留。如果這個取值設定不合理,容易引起Cluster結構的混亂。
另一個問題是tablespace_name,Cluster物件既然包括了tablespace資訊,就必然是佔用空間的,也必然以segment的形式出現。
SQL> select SEGMENT_TYPE, extents, HEADER_FILE, HEADER_BLOCK, BYTES, BLOCKS from dba_segments where wner='TEST' and segment_name='EMP_DEPT';
SEGMENT_TYPE EXTENTS HEADER_FILE HEADER_BLOCK BYTES BLOCKS
------------------ ---------- ----------- ------------ ---------- ----------
CLUSTER 1 4 522 65536 8
注意:此時我們沒有建立資料表或者索引,但是cluster segment已經存在出現。下面我們依託cluster emp_dept建立資料表。
SQL> create table emp (empno number, empname varchar2(10), deptno number) cluster emp_dept(deptno);
Table created
SQL> select SEGMENT_TYPE, extents, HEADER_FILE, HEADER_BLOCK, BYTES, BLOCKS from dba_segments where wner='TEST' and segment_name='EMP_DEPT';
SEGMENT_TYPE EXTENTS HEADER_FILE HEADER_BLOCK BYTES BLOCKS
------------------ ---------- ----------- ------------ ---------- ----------
CLUSTER 1 4 522 65536 8
SQL> select SEGMENT_TYPE, extents, HEADER_FILE, HEADER_BLOCK, BYTES, BLOCKS from dba_segments where wner='TEST' and segment_name='EMP';
SEGMENT_TYPE EXTENTS HEADER_FILE HEADER_BLOCK BYTES BLOCKS
------------------ ---------- ----------- ------------ ---------- ----------
依託cluster建立資料表的時候,要指定出哪個欄位是cluster的key鍵值。從段結構資料字典中,我們不能看到資料表的段資訊,只有cluster的段資訊。從dba_tables中,我們的確看到資料表成功建立。
SQL> select segment_created from dba_tables where wner='TEST' and table_name='EMP';
SEGMENT_CREATED
---------------
YES
此時,我們嘗試往資料表emp新增資料,是被禁止的。
SQL> insert into emp select empno, ename, deptno from scott.emp;
insert into emp select empno, ename, deptno from scott.emp
ORA-02032: 聚簇表無法在簇索引建立之前使用
在這裡,我們意識到使用cluster還需要建立專門的cluster index。為了進行連線測試,先建立第二張資料表。
SQL> create table dept (deptno number primary key, deptname varchar2(10)) cluster emp_dept(deptno);
Table created
SQL> select segment_created from dba_tables where wner='TEST' and table_name='DEPT';
SEGMENT_CREATED
---------------
YES
同時,建立了需要的索引結構。
SQL> create index idx_emp_dept on cluster emp_dept;
Index created
SQL> select SEGMENT_TYPE, extents, HEADER_FILE, HEADER_BLOCK, BYTES, BLOCKS from dba_segments where wner='TEST' and segment_name in ('EMP_DEPT','IDX_EMP_DEPT');
SEGMENT_TYPE EXTENTS HEADER_FILE HEADER_BLOCK BYTES BLOCKS
------------------ ---------- ----------- ------------ ---------- ----------
INDEX 1 4 538 65536 8
CLUSTER 1 4 522 65536 8
SQL> select SEGMENT_TYPE, extents, HEADER_FILE, HEADER_BLOCK, BYTES, BLOCKS from dba_segments where wner='TEST' and segment_name='EMP';
SEGMENT_TYPE EXTENTS HEADER_FILE HEADER_BLOCK BYTES BLOCKS
------------------ ---------- ----------- ------------ ---------- ----------
SQL> select SEGMENT_TYPE, extents, HEADER_FILE, HEADER_BLOCK, BYTES, BLOCKS from dba_segments where wner='TEST' and segment_name='DEPT';
SEGMENT_TYPE EXTENTS HEADER_FILE HEADER_BLOCK BYTES BLOCKS
------------------ ---------- ----------- ------------ ---------- ----------
--Index後設資料資訊
SQL> select index_type, table_name, table_type, UNIQUENESS from dba_indexes where wner='TEST' and index_name='IDX_EMP_DEPT';
INDEX_TYPE TABLE_NAME TABLE_TYPE UNIQUENESS
--------------------------- ---------------------------- ----------- ----------
CLUSTER EMP_DEPT CLUSTER UNIQUE
我們建立了兩張資料表和一個索引,只有cluster和索引成為了段物件。明顯的是兩個資料表都包括儲存在了cluster段結構中。
建立索引的過程和普通索引是不同的。我們沒有給資料表建索引,而是給cluster物件。從dba_indexes檢視中,可以看到差異和不同。
下面我們灌入資料。
SQL> insert into dept select deptno, dname from scott.dept;
4 rows inserted
SQL> insert into emp select empno, ename, deptno from scott.emp;
14 rows inserted
SQL> commit;
Commit complete
此時,段結構依然維持一個cluster和一個索引的形態。
SQL> select SEGMENT_TYPE, extents, HEADER_FILE, HEADER_BLOCK, BYTES, BLOCKS from dba_segments where wner='TEST' and segment_name='EMP';
SEGMENT_TYPE EXTENTS HEADER_FILE HEADER_BLOCK BYTES BLOCKS
------------------ ---------- ----------- ------------ ---------- ----------
SQL> select SEGMENT_TYPE, extents, HEADER_FILE, HEADER_BLOCK, BYTES, BLOCKS from dba_segments where wner='TEST' and segment_name='DEPT';
SEGMENT_TYPE EXTENTS HEADER_FILE HEADER_BLOCK BYTES BLOCKS
------------------ ---------- ----------- ------------ ---------- ----------
SQL> select SEGMENT_TYPE, extents, HEADER_FILE, HEADER_BLOCK, BYTES, BLOCKS from dba_segments where wner='TEST' and segment_name in ('EMP_DEPT','IDX_EMP_DEPT');
SEGMENT_TYPE EXTENTS HEADER_FILE HEADER_BLOCK BYTES BLOCKS
------------------ ---------- ----------- ------------ ---------- ----------
CLUSTER 1 4 522 65536 8
INDEX 1 4 538 65536 8
使用cluster最大的好處在於連線,我們檢視一下連線情況下的執行計劃。
SQL> explain plan for select * from emp a, dept b where a.deptno=b.deptno;
Explained
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------
Plan hash value: 1709228156
-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 14 | 350 | 6 (0)| 00:0
| 1 | NESTED LOOPS | | 14 | 350 | 6 (0)| 00:0
| 2 | TABLE ACCESS FULL | DEPT | 4 | 48 | 3 (0)| 00:0
| 3 | TABLE ACCESS CLUSTER| EMP | 4 | 52 | 1 (0)| 00:0
|* 4 | INDEX UNIQUE SCAN | IDX_EMP_DEPT | 1 | | 0 (0)| 00:0
-------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("A"."DEPTNO"="B"."DEPTNO")
16 rows selected
cluster本質上就是一個容器,如果我們需要刪除cluster,需要將其中資料表物件全部刪除之後,方可執行。或者使用including tables子句。
SQL> drop cluster emp_dept;
drop cluster emp_dept
ORA-00951: 簇非空
SQL> drop cluster emp_dept including tables;
Cluster dropped
本部分介紹的是B樹聚簇,也是簡單的一種聚簇形式。下面我們來討論Hash Cluster的特點。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/17203031/viewspace-774405/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 【實驗】【聚簇】聚簇(Cluster)和聚簇表(Cluster Table)的建立與總結
- oracle簇clusterOracle
- Oracle聚簇表Oracle
- ORACLE 聚簇因子優化Oracle優化
- oracle 聚簇表學習Oracle
- 什麼是Oracle簇(CLUSTER)表Oracle
- oracle cluster(簇)的簡單使用Oracle
- 淺談聚簇索引與非聚簇索引索引
- 聚簇索引索引
- MySQL中的聚簇索引和非聚簇索引MySql索引
- MySQL聚簇索引和非聚簇索引的原理及使用MySql索引
- 一分鐘明白MySQL聚簇索引和非聚簇索引MySql索引
- 聚簇表簡介
- 聚簇因子的理解
- 資料庫表,索引(索引組織表,聚簇表,聚簇索引,)資料庫索引
- 聚簇索引和非聚簇索引到底有什麼區別?索引
- 一看就懂的MySQL的聚簇索引,以及聚簇索引是如何長高的MySql索引
- InnoDB學習(八)之 聚簇索引索引
- MySQL 聚簇索引 和覆蓋索引MySql索引
- Oracle的簇與簇表Oracle
- 資料庫聚簇索引——not null條件對唯一鍵索引成為聚簇索引的影響資料庫索引Null
- MySQL 聚簇索引一定是主鍵嗎MySql索引
- MySQL innodb如何選擇一個聚簇索引MySql索引
- oracle中的簇Oracle
- 【效能優化】Oracle 效能優化:降低列值聚簇因子 提高查詢效率優化Oracle
- 聚簇因子和執行計劃的聯絡
- 淺談索引系列之聚簇因子(clustering_factor)索引
- clustering factor索引聚簇因子和執行計劃索引
- 【效能最佳化】Oracle 效能最佳化:降低列值聚簇因子 提高查詢效率Oracle
- 【Mysql】InnoDB 中的聚簇索引、二級索引、聯合索引MySql索引
- 理解索引和聚簇——效能調整手冊和參考索引
- [MySQL]為什麼非聚簇索引不儲存資料位置MySql索引
- 聊聊Oracle Data Recovery Advisor(DRA)(上)Oracle
- 聊聊Oracle 11g中的Reference Partition(上)Oracle
- Oracle對錶、索引和簇的分析Oracle索引
- Oracle Cluster Time ManagementOracle
- 聊聊Oracle可傳輸表空間(Transportable Tablespace)(上)Oracle
- 聊聊Oracle 11g的Snapshot Standby Database(上)OracleDatabase