Sau khi lướt google nhiều ngày tôi đã tìm thấy ví dụ đơn giản và rõ ràng nhất để lấy lại không gian trống trong không gian bảng sau khi xóa. Tôi hi vọng cái này giúp được
Liên kết: http://www.dbforums.com/oracle/976248-how-reduce-tablespaces-use-space-after-delete-records-2.html
giải pháp:
ALTER TABLE MOVE demo
Hãy tạo một bảng có 9999 hàng trong đó, mỗi hàng có kích thước khoảng 1k:
SQL> create table t (x char(1000) default 'x' primary key);
Table created.
SQL> insert /*+ append nologging */ into t(x) select rownum from all_objects where rownum < 10000;
9999 rows created.
SQL> commit;
Commit complete.
Bảng này có 29 phạm vi được phân bổ cho nó, với tổng số 14,6M:
SQL> select count(*), sum(bytes) from user_extents where segment_name='T';
COUNT(*) SUM(BYTES)
---------- ----------
29 14680064
Hãy xóa TẤT CẢ các hàng:
SQL> delete from t;
9999 rows deleted.
SQL> commit;
Commit complete.
Bây giờ- "bất ngờ" - bảng vẫn sử dụng cùng mức độ:
SQL> select count(*), sum(bytes) from user_extents where segment_name='T';
COUNT(*) SUM(BYTES)
---------- ----------
29 14680064
Tại sao ? Bởi vì ngay cả khi bạn xóa tất cả các hàng của bảng, High Water Mark vẫn không bị giảm - nó không bao giờ giảm, để cho phép đồng thời tối đa (Oracle rất nghiêm túc về việc tối đa hóa đồng thời tức là hiệu suất và khả năng mở rộng; đó là lý do chính đằng sau thành công của nó trong các ứng dụng Doanh nghiệp).
Việc sắp xếp lại không gian chưa sử dụng (= không gian phía trên CTM) không giúp ích nhiều (vì không có nhiều không gian chưa sử dụng phía trên CTM):
SQL> alter table t deallocate unused;
Table altered.
SQL> select count(*), sum(bytes) from user_extents where segment_name='T';
COUNT(*) SUM(BYTES)
---------- ----------
29 13959168
Bây giờ, hãy M CHUYỂN bảng, về bản chất có nghĩa là sao chép bảng (bao gồm cả kích hoạt, ràng buộc, v.v.), chuyển các hàng, thả bảng "cũ" và đổi tên mới - tất cả được tạo bởi kernel, vì vậy siêu an toàn ngay cả trong trường hợp máy / máy chủ bị lỗi:
SQL> alter table t move;
Table altered.
Bây giờ, chúng ta chỉ có phạm vi ban đầu được phân bổ:
SQL> select count(*), sum(bytes) from user_extents where segment_name='T';
COUNT(*) SUM(BYTES)
---------- ----------
1 65536
Hãy cẩn thận: thông thường xảy ra rằng nhiều / tất cả các chỉ mục trên bảng là KHÔNG THỂ sau khi di chuyển (không phải trong trường hợp này nhưng tôi đang chạy 9.2.0.4, phiên bản mới nhất, có thể đã tối ưu hóa quy trình trong trường hợp các bảng hoàn toàn trống ):
SQL> col table_name form a30
SQL> col index_name form a30
SQL> set lines 123
SQL> select table_name, index_name, status from user_indexes where table_name='T';
TABLE_NAME INDEX_NAME STATUS
------------------------------ ------------------------------ ------------------------
T SYS_C002573 VALID
Nếu TÌNH TRẠNG không có giá trị, bạn có thể chỉ cần xây dựng lại thủ công (các) chỉ mục:
SQL> alter index SYS_C002573 rebuild;
Index altered.
Hoặc bạn có thể tự động hóa toàn bộ quá trình:
set serveroutput on size 100000
begin
for n in (select index_name from user_indexes where status <> 'VALID') loop
dbms_output.put_line ('rebuilding ' || n.index_name);
execute immediate 'alter index ' || n.index_name || ' rebuild';
end loop;
end;
/
Ví dụ: hãy đặt thủ công chỉ mục thành UNUSABLE:
SQL> alter index SYS_C002573 unusable;
Index altered.
SQL> set serveroutput on size 100000
SQL> begin
2 for n in (select index_name from user_indexes where status <> 'VALID') loop
3 dbms_output.put_line ('rebuilding ' || n.index_name);
4 execute immediate 'alter index ' || n.index_name || ' rebuild';
5 end loop;
6 end;
7 /
rebuilding SYS_C002573
PL/SQL procedure successfully completed.
HTH