今天做一个关于回收表空间的测试,下面看具体过程:
[oracle@ora11g ~]$ sqlplus / as sysdba
SQL*Plus: Release 11.2.0.4.0 Production on Sun May 31 17:10:14 2015
Copyright (c) 1982, 2013, Oracle. All rights reserved.
Connected to an idle instance.
SQL> startup
ORACLE instance started.
Total System Global Area 835104768 bytes
Database mounted.
Database opened.
SQL> select ts#,name from v$tablespace;
TS# NAME
---------- ------------------------------
SQL> select instance_name from v$instance;
INSTANCE_NAME
----------------
ora11g
--创建测试表空间test、用户zlm并设置test为默认表空间
SQL> create tablespace test datafile '/u01/app/oracle/oradata/ora11g/test01.dbf' size 500m autoextend on next 10m;
Tablespace created.
SQL> create user zlm identified by zlm;
User created.
SQL> alter user zlm default tablespace test;
User altered.
SQL> grant dba to zlm;
Grant succeeded.
SQL> conn zlm/zlm
Connected.
--创建测试表t1
SQL> create table t1 as select * from dba_objects;
Table created.
SQL> select count(*) from t1;
COUNT(*)
----------
86965
--增加记录数量以便更好地观察效果
SQL> insert into t1 select * from t1;
86965 rows created.
SQL> /
173930 rows created.
SQL> /
347860 rows created.
SQL> select tablespace_name,table_name from dba_tables where owner='ZLM';
------------------------------ ------------------------------
由于设置过默认表空间,因此t1表创建在test表空间上
SQL> select bytes/1024/1024 from dba_segments where segment_name='T1';
BYTES/1024/1024
---------------
80
目前60多万条记录共占用了表空间80M大小
SQL> select index_name,table_name,tablespace_name from dba_indexes where owner='ZLM';
no rows selected
通过CTAS方式创建的表,不会讲原表上的索引和约束带过来,需要自己创建
SQL> create index idx_t1_oid on t1(object_id);
Index created.
SQL> select index_name,table_name,tablespace_name from dba_indexes where owner='ZLM';
TABLE_NAME
------------------------------ ------------------------------ ------------------------------
T1
TEST
索引默认表空间也是为test
--查看directory目录
SQL> col owner for a5
SQL> col directory_name for a25
SQL> col directory_path for a80
SQL> select * from dba_directories;
DIRECTORY_PATH
----- ------------------------- --------------------------------------------------------------------------------
/u01/app/oracle/product/11.2.0/dbhome_1/demo/schema/order_entry//2002/Sep
/u01/app/oracle/product/11.2.0/dbhome_1/demo/schema/order_entry/
/u01/app/oracle/product/11.2.0/dbhome_1/demo/schema/log/
/u01/app/oracle/product/11.2.0/dbhome_1/demo/schema/product_media/
/u01/app/oracle/product/11.2.0/dbhome_1/demo/schema/sales_history/
/u01/app/oracle/product/11.2.0/dbhome_1/rdbms/xml
/u01/app/oracle/product/11.2.0/dbhome_1/ccr/hosts/ora11g/state
SYS DATA_PUMP_DIR /u01/app/oracle/admin/ora11g/dpdump/
/u01/app/oracle/product/11.2.0/dbhome_1/ccr/state
--使用系统默认的directory将测试表t1导出备份
[oracle@ora11g ~]$ expdp zlm/zlm directory=data_pump_dir dumpfile=t1.dmp logfile=t1.log tables=t1 indexes=y
Export: Release 11.2.0.4.0 - Production on Sun May 31 18:36:35 2015
Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.
Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Legacy Mode Active due to the following parameters:
Legacy Mode Parameter: "indexes=TRUE" Location: Command Line, ignored.
Legacy Mode has set reuse_dumpfiles=true parameter.
Starting "ZLM"."SYS_EXPORT_TABLE_01": zlm/******** directory=data_pump_dir dumpfile=t1.dmp logfile=t1.log tables=t1 reuse_dumpfiles=true
Estimate in progress using BLOCKS method...
Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
80 MB
Processing object type TABLE_EXPORT/TABLE/TABLE
Processing object type TABLE_EXPORT/TABLE/INDEX/INDEX
Processing object type TABLE_EXPORT/TABLE/INDEX/STATISTICS/INDEX_STATISTICS
67.38 MB 695720 rows
Master table "ZLM"."SYS_EXPORT_TABLE_01" successfully loaded/unloaded
******************************************************************************
Dump file set for ZLM.SYS_EXPORT_TABLE_01 is:
/u01/app/oracle/admin/ora11g/dpdump/t1.dmp
Job "ZLM"."SYS_EXPORT_TABLE_01" successfully completed at Sun May 31 18:36:46 2015 elapsed 0 00:00:10
从导出结果看,占用的逻辑空间评估值为80M,与之前查询出占用的表空间大小相同,60多W行,生成的dump文件大小为67.38M
--开始删除记录
SQL> set timing on
SQL> delete from t1 where rownum<=200000;
200000 rows deleted.
Elapsed: 00:00:15.95
SQL> set autot off
SQL> commit;
Commit complete.
SQL> select count(*) from t1;
COUNT(*)
----------
495720
SQL> select bytes/1024/1024 from dba_segments where segment_name='T1';
BYTES/1024/1024
---------------
80
删除完20W条记录后,可以看到占用的空间并没有被释放,仍然是80M
SQL> alter table t1 move;
Table altered.
SQL> select bytes/1024/1024 from dba_segments where segment_name='T1';
BYTES/1024/1024
---------------
57
对表执行move操作后,占用的空间才降下来,变成57M
TABLE_NAME TABLESPACE_NAME
------------------------------ ------------------------------ ------------------------------ --------
T1 TEST UNUSABLE
注意,对表进行move之后,由于rowid的改变,会引起索引失效,状态为“UNUSABLE”
SQL> set timing on
SQL> delete from t1 where rownum<=200000;
200000 rows deleted.
Elapsed: 00:00:12.31
SQL> set timing off
SQL> commit;
Commit complete.
SQL> select count(*) from t1;
COUNT(*)
----------
295720
SQL> select bytes/1024/1024 from dba_segments where segment_name='T1';
BYTES/1024/1024
---------------
继续删除20W条记录后,仍然为占用57M大小的表空间
SQL> create tablespace test2 datafile '/u01/app/oracle/oradata/ora11g/test02.dbf' size 500m autoextend on next 10m;
Tablespace created.
SQL> alter table t1 move tablespace test2;
Table altered.
TABLE_NAME
TABLESPACE_NAME
------------------------------ ------------------------------ ------------------------------ --------
T1
TEST
SQL> select table_name,tablespace_name from dba_tables where owner='ZLM';
------------------------------ ------------------------------
TEST2
这次将表移动到test2的表空间上,但索引仍然在test表空间上面
SQL> set autot trace
SQL> select count(*) from t1 where object_id<10000;
Execution Plan
----------------------------------------------------------
Plan hash value: 3724264953
---------------------------------------------------------------------------
| Name | Rows | Bytes | Cost (%CPU)| Time
---------------------------------------------------------------------------
|
1 | 13 | 1170 (1)| 00:00:15 |
|
1 | 13 |
|
TABLE ACCESS FULL| T1 | 35782 | 454K| 1170 (1)| 00:00:15 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("OBJECT_ID"<10000)
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
4307 consistent gets
4465 physical reads
116 redo size
528 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
由于move到了test2表空间上,同样的,索引也是失效状态,因为执行计划中走了全表扫描
--重建索引
SQL> alter index idx_t1_oid rebuild;
Index altered.
SQL> select count(*) from t1 where object_id<10000;
Execution Plan
----------------------------------------------------------
Plan hash value: 3794164521
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
| 1 | 13 | 88
| 1 | 13 |
|
INDEX RANGE SCAN| IDX_T1_OID | 35782 | 454K| 88
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_ID"<10000)
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
147 consistent gets
528 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
重建索引后,就可以走索引范围扫描了
SQL> set autot off
SQL> select bytes/1024/1024 from dba_segments where segment_name='T1';
BYTES/1024/1024
---------------
34
由于第2次move,占用的空间又减少了,现在变为34M
SQL> select index_name,table_name,tablespace_name,status from dba_indexes where owner='ZLM';
TABLE_NAME
TABLESPACE_NAME
------------------------------ ------------------------------ ------------------------------ --------
T1
TEST
VALID
此时索引状态变为valid,表示又可以正常使用了
--将表move回原来的表空间
SQL> alter table t1 move tablespace test;
Table altered.
SQL> select index_name,table_name,tablespace_name,status from dba_indexes where owner='ZLM';
TABLE_NAME
TABLESPACE_NAME
------------------------------ ------------------------------ ------------------------------ --------
T1
TEST
UNUSABLE
SQL> alter index idx_t1_oid rebuild;
Index altered.
SQL> select index_name,table_name,tablespace_name,status from dba_indexes where owner='ZLM';
TABLE_NAME
TABLESPACE_NAME
------------------------------ ------------------------------ ------------------------------ --------
T1
TEST
VALID
总结:
只要对表执行过move操作,都是需要重建索引的,无论是在原来的表空间还是另外的表空间,执行完操作后,必须对索引进行重建。另外需要注意的是,move表是会产生锁资源占用的,因此,不建议在业务繁忙期间进行该操作。