先试试purge recyclebin; 或者,运行下面的存储过程,把输出的sql跑一遍,注意修改表空间名称 set serveroutput on;DECLARE type SQL_COLL IS TABLE OF VARCHAR2(4000); v_sql_coll SQL_COLL; v_src_tablespace varchar2(4000); v_des_tablespace varchar2(4000); v_start NUMBER; BEGIN v_src_tablespace := 'USERS'; v_des_tablespace := 'USERS'; --移动表 select 'alter table ' || owner || '.' || table_name || ' move tablespace ' || v_des_tablespace || ' ;' bulk collect into V_SQL_COLL from dba_tables where tablespace_name = v_src_tablespace order by 1; if V_SQL_COLL.count > 0 then for i in V_SQL_COLL.first .. V_SQL_COLL.last loop v_start := DBMS_UTILITY.get_time; dbms_output.put_line(V_SQL_COLL(i)); end loop; end if; END; /DECLARE type SQL_COLL IS TABLE OF VARCHAR2(4000); v_sql_coll SQL_COLL; v_src_tablespace varchar2(4000); v_des_tablespace varchar2(4000); v_start NUMBER; BEGIN v_src_tablespace := 'USERS'; v_des_tablespace := 'USERS'; --重建索引 select 'alter index ' || owner || '.' || index_name || ' rebuild tablespace ' || v_des_tablespace || ' ;' bulk collect into V_SQL_COLL from dba_indexes where tablespace_name = v_src_tablespace and index_type != 'LOB' order by 1; if V_SQL_COLL.count > 0 then for i in V_SQL_COLL.first .. V_SQL_COLL.last loop dbms_output.put_line(V_SQL_COLL(i)); end loop; end if; END; /DECLARE type SQL_COLL IS TABLE OF VARCHAR2(4000); v_sql_coll SQL_COLL; v_src_tablespace varchar2(4000); v_des_tablespace varchar2(4000); v_start NUMBER; BEGIN v_src_tablespace := 'USERS'; v_des_tablespace := 'USERS'; --移动大字段 select 'alter table ' || owner || '.' || table_name || ' move tablespace || v_des_tablespace || lob (' || column_name || ') store as (tablespace ' || v_des_tablespace ||') ;' bulk collect into V_SQL_COLL from dba_lobs where tablespace_name = v_src_tablespace order by 1; if V_SQL_COLL.count > 0 then for i in V_SQL_COLL.first .. V_SQL_COLL.last loop dbms_output.put_line(V_SQL_COLL(i)); end loop; end if; END; /
在oracle concepts中有提到: In general, the extents of a segment do not return to the tablespace until you drop the schema object whose data is stored in the segment (using a DROP TABLE or DROP CLUSTER statement). Exceptions to this include the following: The owner of a table or cluster, or a user with the DELETE ANY privilege, can truncate the table or cluster with a TRUNCATE...DROP STORAGE statement. A database administrator (DBA) can deallocate unused extents using the following SQL syntax:ALTER TABLE table_name DEALLOCATE UNUSED; Periodically, Oracle deallocates one or more extents of a rollback segment if it has the OPTIMAL size specified. 一般来说,在用户将一个段对应的方案对象移除(使用 DROP TABLE 或 DROP CLUSTER 语句)之前,此段的数据扩展(extent)不会被回收到表空间(tablespace)中,但是以下情况例外: 表,簇表的所有者(owner)或拥有 DELETE ANY 权限的用户, 可以使用 TRUNCATE...DROP STORAGE 语句将表,簇表的数据清除 DBA 可以使用以下语法收回一个段中未使用的数据扩展: ALTER TABLE table_name DEALLOCATE UNUSED; 如果用户为回滚段(rollback segment)设定了 OPTIMAL 参数,Oracle将周期性地从其中回收数据扩展。
When extents are freed, Oracle modifies the bitmap in the datafile (for locally managed tablespaces) or updates the data dictionary (for dictionary managed tablespaces) to reflect the regained extents as available space. Any data in the blocks of freed extents becomes inaccessible. 当数据扩展(extent)被释放后,Oracle修改数据文件(datafile)中的位图(bitmap)(对于本地管理的表空间)或更新数据字典(对于数据字典管理的表空间),将回收的数据扩展视为可用空间。被释放的数据扩展中的数据无法继续访问。这可以说明为什么高水位线不下降吧
或者,运行下面的存储过程,把输出的sql跑一遍,注意修改表空间名称
set serveroutput on;DECLARE
type SQL_COLL IS TABLE OF VARCHAR2(4000);
v_sql_coll SQL_COLL;
v_src_tablespace varchar2(4000);
v_des_tablespace varchar2(4000);
v_start NUMBER;
BEGIN
v_src_tablespace := 'USERS';
v_des_tablespace := 'USERS'; --移动表
select 'alter table ' || owner || '.' || table_name ||
' move tablespace ' || v_des_tablespace || ' ;' bulk collect
into V_SQL_COLL
from dba_tables
where tablespace_name = v_src_tablespace
order by 1;
if V_SQL_COLL.count > 0 then
for i in V_SQL_COLL.first .. V_SQL_COLL.last loop
v_start := DBMS_UTILITY.get_time;
dbms_output.put_line(V_SQL_COLL(i));
end loop;
end if;
END;
/DECLARE
type SQL_COLL IS TABLE OF VARCHAR2(4000);
v_sql_coll SQL_COLL;
v_src_tablespace varchar2(4000);
v_des_tablespace varchar2(4000);
v_start NUMBER;
BEGIN
v_src_tablespace := 'USERS';
v_des_tablespace := 'USERS'; --重建索引
select 'alter index ' || owner || '.' || index_name ||
' rebuild tablespace ' || v_des_tablespace || ' ;' bulk collect
into V_SQL_COLL
from dba_indexes
where tablespace_name = v_src_tablespace
and index_type != 'LOB'
order by 1;
if V_SQL_COLL.count > 0 then
for i in V_SQL_COLL.first .. V_SQL_COLL.last loop
dbms_output.put_line(V_SQL_COLL(i));
end loop;
end if;
END;
/DECLARE
type SQL_COLL IS TABLE OF VARCHAR2(4000);
v_sql_coll SQL_COLL;
v_src_tablespace varchar2(4000);
v_des_tablespace varchar2(4000);
v_start NUMBER;
BEGIN
v_src_tablespace := 'USERS';
v_des_tablespace := 'USERS'; --移动大字段
select 'alter table ' || owner || '.' || table_name ||
' move tablespace || v_des_tablespace || lob (' || column_name ||
') store as (tablespace ' || v_des_tablespace ||') ;' bulk collect
into V_SQL_COLL
from dba_lobs
where tablespace_name = v_src_tablespace
order by 1;
if V_SQL_COLL.count > 0 then
for i in V_SQL_COLL.first .. V_SQL_COLL.last loop
dbms_output.put_line(V_SQL_COLL(i));
end loop;
end if;
END;
/
下面我们来谈一下Oracle中Select语句的特性。Select语句会对表中的数据进行一次扫描,但是究竟扫描多少数据存储块呢,这个并不是说数据库中有多少数据,Oracle就扫描这么大的数据块,而是Oracle会扫描高水位线以下的数据块。现在来想象一下,如果刚才是一张刚刚建立的空表,你进行了一次Select操作,那么由于高水位线HWM在最低的0位置上,所以没有数据块需要被扫描,扫描时间会极短。而如果这个时候你首先插入了一千万条数据,然后再用delete语句删除这一千万条数据。由于插入了一千万条数据,所以这个时候的高水位线就在一千万条数据这里。后来删除这一千万条数据的时候,由于delete语句不影响高水位线,所以高水位线依然在一千万条数据这里。这个时候再一次用select语句进行扫描,虽然这个时候表中没有数据,但是由于扫描是按照高水位线来的,所以需要把一千万条数据的存储空间都要扫描一次,也就是说这次扫描所需要的时间和扫描一千万条数据所需要的时间是一样多的。所以有时候有人总是经常说,怎么我的表中没有几条数据,但是还是这么慢呢,这个时候其实奥秘就是这里的高水位线了。
那有没有办法让高水位线下降呢,其实有一种比较简单的方法,那就是采用TRUNCATE语句进行删除数据。采用TRUNCATE语句删除一个表的数据的时候,类似于重新建立了表,不仅把数据都删除了,还把HWM给清空恢复为0。所以如果需要把表清空,在有可能利用TRUNCATE语句来删除数据的时候就利用TRUNCATE语句来删除表,特别是那种数据量有可能很大的临时存储表。
delete不降
truncate降
再不就drop table
再 create table
In general, the extents of a segment do not return to the tablespace until you drop the schema object whose data is stored in the segment (using a DROP TABLE or DROP CLUSTER statement). Exceptions to this include the following:
The owner of a table or cluster, or a user with the DELETE ANY privilege, can truncate the table or cluster with a TRUNCATE...DROP STORAGE statement.
A database administrator (DBA) can deallocate unused extents using the following SQL syntax:ALTER TABLE table_name DEALLOCATE UNUSED;
Periodically, Oracle deallocates one or more extents of a rollback segment if it has the OPTIMAL size specified.
一般来说,在用户将一个段对应的方案对象移除(使用 DROP TABLE 或 DROP CLUSTER 语句)之前,此段的数据扩展(extent)不会被回收到表空间(tablespace)中,但是以下情况例外:
表,簇表的所有者(owner)或拥有 DELETE ANY 权限的用户, 可以使用 TRUNCATE...DROP STORAGE 语句将表,簇表的数据清除
DBA 可以使用以下语法收回一个段中未使用的数据扩展:
ALTER TABLE table_name DEALLOCATE UNUSED; 如果用户为回滚段(rollback segment)设定了 OPTIMAL 参数,Oracle将周期性地从其中回收数据扩展。
When extents are freed, Oracle modifies the bitmap in the datafile (for locally managed tablespaces) or updates the data dictionary (for dictionary managed tablespaces) to reflect the regained extents as available space. Any data in the blocks of freed extents becomes inaccessible.
当数据扩展(extent)被释放后,Oracle修改数据文件(datafile)中的位图(bitmap)(对于本地管理的表空间)或更新数据字典(对于数据字典管理的表空间),将回收的数据扩展视为可用空间。被释放的数据扩展中的数据无法继续访问。这可以说明为什么高水位线不下降吧
为何shift+delete却会彻底删除并会释放空间呢?^_^,一样的道理