您好,登錄后才能下訂單哦!
如何理解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樹聚簇,也是簡單的一種聚簇形式。
看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。