一.段的類型:
1.什麼是段:段是存儲單元。
1.段的類型有:
表 分區表 簇表 索引 索引組織表(IOT表) 分區索引 臨時段 undo段 lob段(blob ,clob) 內嵌表(record類型,table類型) 啟動段 :打開數據庫時要裝入的數據字典系統信息,故在系統表空間內。
注意:smon 回收不用的臨時段和undo段。
2.表:
表是存儲數據的邏輯單位。 表的功能: 存儲、管理數據的基本單元, 表的類型: 普通表:堆表,
例:查詢表的行的平均長度 AVG_ROW_LEN 平均長度 avg_space 平均空間 SQL> select table_name,tablespace_name,blocks,pct_free,pct_used,avg_space,AVG_ROW_LEN from dba_tables where table_name like 'EMP%';
TABLE_NA TABLESPACE_N BLOCKS PCT_FREE PCT_USED AVG_SPACE AVG_ROW_LEN -------- ------------ ---------- ---------- ---------- ---------- ----------- EMP1 SYSTEM 44 10 40 0 38 EMP USERS 1 10 40 0 38 EMPLX LXTBS2 10 10 40 1322 38
例:查詢表默認的pctfree 和pctused 以及修改 SQL> select table_name,tablespace_name,blocks,pct_free,pct_used from dba_tables where table_name like 'EMP%';
TABLE_NA TABLESPACE_N BLOCKS PCT_FREE PCT_USED -------- ------------ ---------- ---------- ---------- EMP1 SYSTEM 44 10 40 EMPLX LXTBS2 10 10 40 EMP USERS 1 10 40
SQL> alter table emplx pctfree 12;
Table altered.
SQL> alter table emplx pctused 42;
Table altered.
3.分區表:
比如一個表尺寸大於2g,oracle建議分區,一個分區內的數據量一般不超過50w左右性能最好,最多不要超過100萬。 range分區方式,按照指定范圍分區,比如按時間分區或值大小分區。 list分區方式,是一種列舉方式進行分區 哈數分區方式, 根據hash算法分區,有oracle管理。
①.分區表的使用詳見:【dba,32】分區表:
②.案例:創建分區索引:
#創建分區表 SQL> CREATE TABLE sales_history 2 (id number(8),name varchar2(30),sales_date date) 3 PARTITION BY RANGE (sales_date) 4 (PARTITION p1 VALUES LESS THAN ( TO_DATE('01-JAN-1999','DD-MON-YYYY')) tablespace users, 5 PARTITION p2 VALUES LESS THAN ( TO_DATE('01-JAN-2000','DD-MON-YYYY')) tablespace users, 6 PARTITION p3 VALUES LESS THAN ( TO_DATE('01-JAN-2001','DD-MON-YYYY')) tablespace users, 7 PARTITION p4 VALUES LESS THAN ( TO_DATE('01-JAN-2002','DD-MON-YYYY')) tablespace users, 8 PARTITION p5 VALUES LESS THAN (MAXVALUE) tablespace users 9 );
Table created. #插入數據 SQL> insert into sales_history values(1,'PC1',to_date('17-FEB-2000','DD-MON-YYYY')); SQL> insert into sales_history values(2,'PC2',to_date('17-FEB-2001','DD-MON-YYYY')) SQL> insert into sales_history values(3,'PC3',to_date('17-FEB-2002','DD-MON-YYYY')); SQL> insert into sales_history values(4,'PC4',to_date('17-FEB-1999','DD-MON-YYYY'));
SQL> insert into sales_history values(5,'PC5',to_date('15-FEB-2000','DD-MON-YYYY')); SQL> insert into sales_history values(6,'PC6',to_date('12-FEB-2001','DD-MON-YYYY')); SQL> insert into sales_history values(7,'PC7',to_date('11-FEB-1998','DD-MON-YYYY')); SQL> insert into sales_history values(8,'PC8',to_date('13-FEB-2002','DD-MON-YYYY'));
SQL> insert into sales_history values(8,'PC8',to_date('13-FEB-2013','DD-MON-YYYY'));
#查詢數據 SQL> select * from sales_history;
ID NAME SALES_DAT ---------- ---------- --------- 7 PC7 11-FEB-98 4 PC4 17-FEB-99 1 PC1 17-FEB-00 5 PC5 15-FEB-00 2 PC2 17-FEB-01 6 PC6 12-FEB-01 3 PC3 17-FEB-02 8 PC8 13-FEB-02 8 PC8 13-FEB-13
9 rows selected. #查詢分區表數據 SQL> select * from sales_history partition(p1);
ID NAME SALES_DAT ---------- ---------- --------- 7 PC7 11-FEB-98
SQL> select * from sales_history partition(p2);
ID NAME SALES_DAT ---------- ---------- --------- 4 PC4 17-FEB-99
SQL> select * from sales_history partition(p3);
ID NAME SALES_DAT ---------- ---------- --------- 1 PC1 17-FEB-00 5 PC5 15-FEB-00
SQL> select * from sales_history partition(p4);
ID NAME SALES_DAT ---------- ---------- --------- 2 PC2 17-FEB-01 6 PC6 12-FEB-01
SQL> select * from sales_history partition(p5);
ID NAME SALES_DAT ---------- ---------- --------- 3 PC3 17-FEB-02 8 PC8 13-FEB-02 8 PC8 13-FEB-13
#創建唯一索引 ,因為數據中id有重復,所以報錯。 SQL> CREATE unique INDEX i_sales_id ON sales_history(id) GLOBAL 2 PARTITION BY HASH (id) 3 (PARTITION pi1 TABLESPACE users, 4 PARTITION pi2 TABLESPACE users, 5 PARTITION pi3 TABLESPACE users, 6 PARTITION pi4 TABLESPACE users) parallel 4;
CREATE unique INDEX i_sales_id ON sales_history(id) GLOBAL * ERROR at line 1: ORA-12801: error signaled in parallel query server P001 ORA-01452: cannot CREATE UNIQUE INDEX; duplicate keys found
#根據rowid查詢和刪除重復數據: SQL> select a.* from sales_history a 2 where a.rowid in ( 3 select min(b.rowid) from sales_history b 4 where b.id=a.id);
ID NAME SALES_DAT ---------- ---------- --------- 7 PC7 11-FEB-98 4 PC4 17-FEB-99 1 PC1 17-FEB-00 5 PC5 15-FEB-00 2 PC2 17-FEB-01 6 PC6 12-FEB-01 3 PC3 17-FEB-02 8 PC8 13-FEB-02
8 rows selected. #查詢出多余的數據 SQL> select a.* from sales_history a 2 where a.rowid not in ( 3 select min(b.rowid) from sales_history b 4 where b.id=a.id);
ID NAME SALES_DAT ---------- ---------- --------- 8 PC8 13-FEB-13
SQL> select a.*,rowid from sales_history a;
ID NAME SALES_DAT ROWID ---------- ---------- --------- ------------------ 7 PC7 11-FEB-98 AAACffAAEAAAAA9AAA 4 PC4 17-FEB-99 AAACfgAAEAAAABFAAA 1 PC1 17-FEB-00 AAACfhAAEAAAABNAAA 5 PC5 15-FEB-00 AAACfhAAEAAAABNAAB 2 PC2 17-FEB-01 AAACfiAAEAAAABVAAA 6 PC6 12-FEB-01 AAACfiAAEAAAABVAAB 3 PC3 17-FEB-02 AAACfjAAEAAAABdAAA 8 PC8 13-FEB-02 AAACfjAAEAAAABdAAB 8 PC8 13-FEB-13 AAACfjAAEAAAABdAAC
9 rows selected. #刪除重復的數據 SQL> delete from sales_history a 2 where a.rowid not in ( 3 select min(b.rowid) from sales_history b 4 where b.id=a.id); SQL> CREATE unique INDEX i_sales_id ON sales_history(id) GLOBAL 2 PARTITION BY HASH (id) 3 (PARTITION pi1 TABLESPACE users, 4 PARTITION pi2 TABLESPACE users, 5 PARTITION pi3 TABLESPACE users, 6 PARTITION pi4 TABLESPACE users) parallel 4;
Index created.
注意:parallel 在生成庫上慎重使用,可能會把cpu的資源消耗干。 注意:對某個字段已做了分區了,是不允許再建立索引分區的。這一點要非常注意。
#創建本地索引 SQL> CREATE INDEX i_sales_date on sales_history(sales_date) local;
Index created. #創建一個不分區的索引 SQL> CREATE INDEX i_sales_name on sales_history(name);
#查詢索引,partitioned 為YES表示分區索引。 SQL> select index_name,index_type,table_name,tablespace_name,partitioned from dba_indexes where table_name='SALES_HISTORY';
INDEX_NAME INDEX_TYPE TABLE_NAME TABLESPACE PAR -------------------- ---------- -------------------- ---------- --- I_SALES_ID NORMAL SALES_HISTORY YES I_SALES_DATE NORMAL SALES_HISTORY YES I_SALES_NAME NORMAL SALES_HISTORY SYSTEM NO
#truncate 分區。 SQL> alter table sales_history truncate partition p2 update indexes; Table truncated.
#重建分區索引 SQL> alter index i_sales_date rebuild partition p3; Index altered.
#添加分區 SQL> alter table sales_history add partition p6 values less than (to_date('2019-01-01','yyyy-mm-dd')) ;
3.2. PARTITION BY REFERENCE: http://blog.itpub.net/9240380/viewspace-752307 http://docs.oracle.com/cd/E11882_01/server.112/e25523/part_admin001.htm#i1006455
4.簇表:
主要用於表和表之間的連接查詢。 訪問不同的表時要訪問不同的段,磁盤會訪問不同的磁道,如果兩個表能存放到一個段,就能提高訪問速度。 一個簇是由共享相同數據塊的一組表組成,因為這些表共享公共的列並且經常一起被使用,所以將這些表組合在一起。 簇表優點: 減少了磁盤i/o並改善了訪問簇表的連接所化的時間。 簇鍵是列或列的組,他們是簇表所共用的創建簇時指定簇鍵的列,
例:創建簇表 #關聯查詢 SQL> select e.empno,e.ename,e.sal,d.deptno,d.dname from scott.emp e,scott.dept d where e.deptno=d.deptno;
14 rows selected.
Execution Plan ---------------------------------------------------------- Plan hash value: 615168685
--------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 14 | 952 | 7 (15)| 00:00:01 | |* 1 | HASH JOIN | | 14 | 952 | 7 (15)| 00:00:01 | | 2 | TABLE ACCESS FULL| DEPT | 4 | 88 | 3 (0)| 00:00:01 | | 3 | TABLE ACCESS FULL| EMP | 14 | 644 | 3 (0)| 00:00:01 | ---------------------------------------------------------------------------
#創建簇鍵 SQL> CREATE CLUSTER emp_dept (deptno NUMBER(3)) 2 SIZE 600 3 TABLESPACE users;
Cluster created. #創建簇表 先創建dept,然後再創建emp表。否則報錯。 SQL> create table dept( 2 DEPTNO NUMBER(3) primary key, 3 DNAME VARCHAR2(14), 4 LOC VARCHAR2(13) 5 ) CLUSTER emp_dept (deptno);
Table created. #創建簇表 SQL> create table emp( 2 EMPNO NUMBER(4) primary key, 3 ENAME VARCHAR2(10), 4 JOB VARCHAR2(9), 5 MGR NUMBER(4), 6 HIREDATE DATE, 7 SAL NUMBER(7,2), 8 COMM NUMBER(7,2), 9 DEPTNO NUMBER(3) references dept(deptno) 10 ) CLUSTER emp_dept (deptno);
Table created. #創建簇索引 SQL> CREATE INDEX emp_dept_index 2 ON CLUSTER emp_dept 3 TABLESPACE users;
Index created. #插入數據 SQL> insert into dept select * from scott.dept;
4 rows created.
SQL> insert into emp select * from scott.emp;
14 rows created.
SQL> commit;
Commit complete. #查詢兩個表的rowid,rowid的前15位相同說明在同一個數據塊中。 SQL> select e.rowid,d.rowid from emp e,dept d where e.deptno=d.deptno;
ROWID ROWID ------------------ ------------------ AAACgFAAEAAAACVAAA AAACgFAAEAAAACVAAB AAACgFAAEAAAACVAAB AAACgFAAEAAAACVAAC AAACgFAAEAAAACVAAC AAACgFAAEAAAACVAAC AAACgFAAEAAAACVAAD AAACgFAAEAAAACVAAB AAACgFAAEAAAACVAAE AAACgFAAEAAAACVAAC AAACgFAAEAAAACVAAF AAACgFAAEAAAACVAAC AAACgFAAEAAAACVAAG AAACgFAAEAAAACVAAA AAACgFAAEAAAACVAAH AAACgFAAEAAAACVAAB AAACgFAAEAAAACVAAI AAACgFAAEAAAACVAAA AAACgFAAEAAAACVAAJ AAACgFAAEAAAACVAAC AAACgFAAEAAAACVAAK AAACgFAAEAAAACVAAB
ROWID ROWID ------------------ ------------------ AAACgFAAEAAAACVAAL AAACgFAAEAAAACVAAC AAACgFAAEAAAACVAAM AAACgFAAEAAAACVAAB AAACgFAAEAAAACVAAN AAACgFAAEAAAACVAAA
14 rows selected.
#掃描方式發生變化 SQL> select e.empno,e.ename,e.sal,d.deptno,d.dname from emp e,dept d where e.deptno=d.deptno;
14 rows selected.
Execution Plan ---------------------------------------------------------- Plan hash value: 805422011
---------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 14 | 952 | 6 (0)| 00:00:01 | | 1 | NESTED LOOPS | | 14 | 952 | 6 (0)| 00:00:01 | | 2 | TABLE ACCESS FULL | DEPT | 4 | 88 | 3 (0)| 00:00:01 | | 3 | TABLE ACCESS CLUSTER| EMP | 4 | 184 | 1 (0)| 00:00:01 | |* 4 | INDEX UNIQUE SCAN | EMP_DEPT_INDEX | 1 | | 0 (0)| 00:00:01 | ----------------------------------------------------------------------------------------
5.索引:
加快查詢速度,索引第一次IO先訪問樹,到葉節點找到rowid,再通過rowid訪問響應的記錄。
6.索引組織表(IOT表):
可以將數據存放在索引的葉節點,不用再訪問不同的段,iot表不能換查詢條件,查詢條件必須建成主鍵約束,如果換查詢條件效率會很低。 iot表存儲時根據主鍵排序進行存儲,所以插入數據時,按順序插入數據。 如果索引組織表中的數據放不下會把一些數據放到溢出表空間。 優點:只要io一次就能找到真實數據。 注意:生產中慎重使用。
例:將多對多的關系表創建索引組織表 SQL> create table students(stud_id number,fname varchar2(30),lname varchar2(30),constraint pk_student primary key(stud_id)); Table created.
SQL> create table classes(class_id number,cname varchar2(30),constraint pk_class primary key(class_id)); Table created.
#創建索引組織表,
SQL> create table attendees(stud_id number,class_id number, 2 constraint pk_stud_class primary key(stud_id,class_id), 3 constraint fk_stud foreign key(stud_id) references students(stud_id), 4 constraint fk_class foreign key(class_id) references classes(class_id) 5 ) organization index;
7.分區索引類型:
①.表是分區表,索引不分區: ②.分區表的全局分區索引: 缺點:在truncate表時,這種索引會失效。 優點:global所以在全局是有序的,所以效率高。 ③.分區表的local分區索引: 語法:create index inx_tab_partition_col table_partition(col1) local; 缺點: 分區上的位圖索引只能為local索引,不能為global全局索引。 local分區索引在每個分區上有序,但在全局是無序的,索引查詢效率沒有全局分區索引高。 優點:在olap系統中應用廣泛,在truncate表時,這種索引不會失效。易於管理。
二.數據塊:(pctfree和pctused,行連接、行遷移、數據塊)
1.數據塊分為三部分:block header(塊頭),free space(空閒空間), row data(數據行)。
2.pctfree 和pctused pctfree就是插入數據到數據塊中,達到pctfree時就不在插入數據,pctfree就是為update預留的空間。 pctused就是數據塊中存放的數據在pctused之下表示數據塊為空塊,在段空間手工管理的情況下,就會把這些數據塊放到鏈表freelist隊列中,用於再次插入數據。
pctfree 太小在update操作時會導致行遷移, pctused 太大在insert操作時會導致行連接。 3.行遷移(row migrate)和行連接(row chain) 行遷移:由於update操作導致原本在該塊中的記錄放不下了,就保留一個該行記錄的地址,然後將該行記錄遷移到其他塊中,但是rowid不變。 行連接: 就是一行數據insert到一個塊時,根本容不下這行數據,該條記錄只能把數據分別放到若干個數據塊中,使用row chain連接起來。long或long row數據類型的時候容易產生行連接。
4.數據塊頭: 塊頭包括表目錄,行目錄。 表目錄: 這部分信息包含了在這個塊中該表或該索引的相關信息。 行目錄: 包含數據塊中的實際行的信息(包括行數據區域中每行的地址) 事務槽 (ITL:interested transaction list): ①. 表初始事務槽是1,索引默認為2,事務表會根據需要動態擴展,用來記錄該數據塊所有發生的事務。如果事務已經提交,那麼這個itl的位置就可以被反復使用了。 ②.多個事務同時修改同一數據塊時,就會有多個事務槽,事務槽被占用完了(數據塊可用的空間被用完) 當再有事務要操作數據塊時,需要等待其他事務提交後,才能進行操作,此時就是事務槽的爭用 查看事務槽:
SQL> select table_name ,tablespace_name,blocks,ini_trans,max_trans from dba_tables where table_name like 'EMP%'; TABLE_NAME TABLESPACE_NAME BLOCKS INI_TRANS MAX_TRANS ------------------------------ --------------- ---------- ---------- ---------- EMP1 SYSTEM 44 1 255 EMP USERS 1 1 255
SQL> select index_name,index_type,table_name,tablespace_name,ini_trans,max_trans from dba_indexes where owner='SCOTT'; INDEX_NAME INDEX_TYPE TABLE_NAME TABLESPACE_NAME INI_TRANS MAX_TRANS ---------- ---------- --------------- --------------- ---------- ---------- PK_EMP NORMAL EMP USERS 2 255 PK_DEPT NORMAL DEPT USERS 2 255
三.段的管理方式(兩種)
自動段空間管理(ASSM)(數據庫默認的管理形式)和手動段空間管理
1.自動段空間管理(ASSM)auto segment space manage 不訪問freelist而是訪問自己段頭的位圖,極大地減少了競爭。 連接列表freelist被位圖所取代,它是一個二進制的數組,能夠快速有效的管理存儲擴展和剩余區塊(free block),因此能夠改善分段存儲本質,assm 表空間上創建的段還有另外一個稱呼叫bitmap managed segments (BMB段)。
assm優點:減輕緩沖區忙等待(buffer busy waits)的負擔,有assm之後,oracle提高了DML並發操作的性能。因為位圖的不同部分可以被同時使用,這樣就消除了尋找剩余空間的串行化。根據oracle的測試結果,使用位圖會消除所用分段頭部的爭奪,還能獲得超快的並發插入操作。消除並發插入的熱快問題和buffer busy wait。
assm的局限性: 無法控制tablespace內部的獨立表和索引的存儲行為 大型對象不能使用assm,而且必須為包含lob數據類型的表創建分離的tablespace。 不能使用assm創建臨時表空間,這是由於排序時臨時分段的短暫特性所決定的。 只用本地管理的tablespace才能使用位圖分段管理。 使用超高容量的dml的時候可能會出現性能上的問題。
注意:不要與內存分配自動管理(asmm)混淆。
2.手動段空間管理(MSSM) 系統會在段頭建立一個fresslist鏈表,我們會把有空閒空間的塊,放到列表中。當塊中的數據量少於pctused會插入freelist。 然而鏈表freelist是串行化操作。 在沒有多個freelist的時候,當數據緩沖內的數據塊由於被另一個dml事務處理鎖定而無法使用的時候,緩沖區忙等待就會發生,當你需要將多個任務插入到同一表格裡的時候,這些任務就被強制等待,而同時oracle會在同時分派剩余的區塊,一次一個(buffer busy wait)。很多用戶都訪問freelist 形成熱塊。
3.兩種段空間的管理比較: 相同點: 主要是管理已經分配給段的數據塊, 不同點: 手工段空間管理方式:pctfree和pctused 都有效。 自動段空間管理方式:只使用pctfree來決定是不是空塊,pctused 被位圖的四個狀態位所取代(如:>75%,50%~75%,50%~25%,<25%)。 assm無法控制tablespace內部的獨立表和索引的存儲行為。 mssm可以控制tablespace內部的獨立表和索引的存儲行為。
4.查看段的管理方式 SQL> select tablespace_name ,contents,status,extent_management,segment_space_management from dba_tablespaces;
TABLESPACE_NAME CONTENTS STATUS EXTENT_MAN SEGMEN ------------------------------ --------- --------- ---------- ------ SYSTEM PERMANENT ONLINE LOCAL MANUAL SYSAUX PERMANENT ONLINE LOCAL AUTO UNDOTBS UNDO ONLINE LOCAL MANUAL USERS PERMANENT ONLINE LOCAL MANUAL TEMPTS2 TEMPORARY ONLINE LOCAL MANUAL LXTBS1 PERMANENT ONLINE LOCAL AUTO LXTBS2 PERMANENT ONLINE LOCAL AUTO LXTBS3 PERMANENT ONLINE LOCAL AUTO TEMPTS TEMPORARY ONLINE LOCAL MANUAL
四.區的管理方式和段的管理方式的區別:
區的管理方式: 區來自表空間,這些數據塊還沒有被分配出去。 段的管理方式:主要是管理已經分配給段的數據塊,
五.創建assm和mssm管理的表空間:
1.創建ASSM段管理的表空間 (數據庫段空間管理默認方式為ASSM) SQL> create tablespace lxtbs1 datafile '/u01/app/oracle/oradata/prod/disk3/lxtbs01.dbf' size 50m segment space management auto; 或者 create tablespace lxtbs1 datafile '/u01/app/oracle/oradata/prod/disk3/lxtbs01.dbf' size 50m; 2.創建MSSM手工管理的表空間 SQL> create tablespace lxtbs2 datafile '/u01/app/oracle/oradata/prod/disk3/lxtbs01.dbf' size 50m segment space management manual;
六.在mssm段管理方式的表空間創建表並設計表空間分配 :
注意:只能在mssm段管理的方式的表空間上才能對表的空間分配進行設計。
#創建表 SQL> create table emplx tablespace lxtbs2 storage(initial 32k next 64k pctincrease 50) as select * from scott.emp; #插入數據 SQL>insert into emplx select * from emplx; #查詢段的空間分配情況 SQL> select segment_name,segment_type,tablespace_name,bytes/1024 k,extents,blocks,initial_extent/1024 init,next_extent/1024 next,pct_increase from dba_segments where segment_name like 'EMP%'; SEGMENT_NA SEGMENT_TYPE TABLESPACE_NAME K EXTENTS BLOCKS INIT NEXT PCT_INCREASE---------- ------------ --------------- ---------- ---------- ---------- ---------- ---------- ------------
EMP TABLE USERS 64 1 8 64 1024
EMPLX TABLE LXTBS2 192 3 24 32 64
EMP1 TABLE SYSTEM 384 6 48 64 1024
七.高水位線:
1.高水位線介紹: (段使用區的最後一個塊的位置叫高水位線), 高水位線是oracle對表進行全表掃描的最後的位置。當數據刪除,高水位線並不會下降。
2.分析表: 實驗比較truncate與delete的區別 使用:analyze table emplx compute statistics;命令分析表(計算表,一般用於小表)。 SQL> analyze table scott.emp estimate statistics;(對表進行估算,一般用於大表)。 SQL> exec DBMS_STATS.GATHER_TABLE_STATS('SCOTT','EMP'); (plsql分析表)。
#查看執行計劃 SQL> select * from emplx;
Execution Plan ---------------------------------------------------------- Plan hash value: 155704778
--------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 3584 | 112K| 8 (0)| 00:00:01 | | 1 | TABLE ACCESS FULL| EMPLX | 3584 | 112K| 8 (0)| 00:00:01 | ---------------------------------------------------------------------------
SQL> select table_name,tablespace_name,blocks, empty_blocks from dba_tables where table_name='EMPLX';
TABLE_NAME TABLESPACE_NAME BLOCKS EMPTY_BLOCKS --------------- --------------- ---------- ------------ EMPLX LXTBS2
#分析表 SQL> analyze table emplx compute statistics;
Table analyzed.
SQL> select table_name,tablespace_name,blocks, empty_blocks from dba_tables where table_name='EMPLX';
TABLE_NAME TABLESPACE_NAME BLOCKS EMPTY_BLOCKS --------------- --------------- ---------- ------------ EMPLX LXTBS2 23 0
#刪除操作, SQL> delete from emplx;
3584 rows deleted.
SQL> commit;
Commit complete. #delete刪除所有數據後沒有降低高水位線,並不會降低全表掃描的代價 SQL> select table_name,tablespace_name,blocks, empty_blocks from dba_tables where table_name='EMPLX';
TABLE_NAME TABLESPACE_NAME BLOCKS EMPTY_BLOCKS --------------- --------------- ---------- ------------ EMPLX LXTBS2 23 0
SQL> select * from emplx;
no rows selected
Execution Plan ---------------------------------------------------------- Plan hash value: 155704778
--------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 3584 | 112K| 8 (0)| 00:00:01 | | 1 | TABLE ACCESS FULL| EMPLX | 3584 | 112K| 8 (0)| 00:00:01 | ---------------------------------------------------------------------------
#執行truncate操作: SQL> truncate table emplx;
Table truncated. #再對進行分析 SQL> analyze table emplx compute statistics;
Table analyzed.
#truncate降低高水位線,只剩余一個區,並且會降低全表掃描的代價 SQL> select table_name,tablespace_name,blocks, empty_blocks from dba_tables where table_name='EMPLX';
TABLE_NAME TABLESPACE_NAME BLOCKS EMPTY_BLOCKS --------------- --------------- ---------- ------------ EMPLX LXTBS2 0 7
3.delete操作後降低表空間。(重點) 使用alter table emplx move 和alter table emplx shrink space都可以用來進行段收縮,降低高水位線,也都可以用來消除行連接和行遷移。 ①.使用alter table move會把表最多收縮到創建表時的storage子句中指定的初始大小,使用later shrink space 不會受此限制。 ②.使用alter table move 之後,索引會無效,需要重建,使用alter table shrink space 則不會。 ③.只能在表所在的表空間是自動段管理(ASSM)的時候,才能使用alter table shrink space; 而move在自動段管理(ASSM)和手動段管理(MSSM)方式下都能使用。 ④.可以使用alter table shrink space compact來對表進行碎片整理,而不調整高水位線,之後再次調用alter table shrink space 來釋放空間。 ⑤.可以使用alter table shrink space cascade;指定了cascade,則收縮行為將級聯到所有支持收縮操作的從屬段,但是 物化視圖、LOB索引、和IOT表例外; ⑥.move 更快 shrink space 較慢。
例:alter table emplx move 和alter table emplx shrink space使用:在MSSM管理的表空間上創建EMPLX表
SQL> select table_name,tablespace_name, blocks,empty_blocks from dba_tables where table_name='EMPLX';
TABLE_NAME TABLESPACE_NAME BLOCKS EMPTY_BLOCKS ------------ ------------------------------ ---------- ------------ EMPLX LXTBS2 0 7
#插入數據 SQL> insert into emplx select * from emplx;
1792 rows created. #分析表 SQL> analyze table emplx compute statistics;
Table analyzed.
SQL> select table_name,tablespace_name, blocks,empty_blocks from dba_tables where table_name='EMPLX';
TABLE_NAME TABLESPACE_NAME BLOCKS EMPTY_BLOCKS ------------ ------------------------------ ---------- ------------ EMPLX LXTBS2 23 0 #刪除數據 SQL> delete from emplx where rownum <=2000;
2000 rows deleted.
SQL> commit;
Commit complete.
SQL> select table_name,tablespace_name, blocks,empty_blocks from dba_tables where table_name='EMPLX';
TABLE_NAME TABLESPACE_NAME BLOCKS EMPTY_BLOCKS ------------ ------------------------------ ---------- ------------ EMPLX LXTBS2 23 0 #使用shrink space 的前奏 SQL> alter table emplx enable row movement ;
Table altered. #使用shrink space降低高水位線,報錯,因為在shrink space只能使用在assm管理段空間方式的表空間上。 SQL> alter table emplx shrink space; alter table emplx shrink space * ERROR at line 1: ORA-10635: Invalid segment or tablespace type
#使用move降低高水位線 SQL> alter table emplx move;
Table altered. #分析表 SQL> analyze table emplx compute statistics;
Table analyzed. #查看塊的使用情況 SQL> select table_name,tablespace_name, blocks,empty_blocks from dba_tables where table_name='EMPLX';
TABLE_NAME TABLESPACE_NAME BLOCKS EMPTY_BLOCKS ------------ ------------------------------ ---------- ------------ EMPLX LXTBS2 10 5