Reklamasi ruang disk datafil bebas / otomatis yang reklamasi


8

Pada Oracle versi 11g:

Setelah Googling, saya tidak dapat menemukan cara sederhana untuk mendapatkan kembali ruang kosong setelah menghapus tabel.

Saya telah menemukan banyak penjelasan, menceritakan bagaimana datafile menjadi terfragmentasi, tumpukan besar pertanyaan membosankan yang harus Anda jalankan untuk memindahkan "ruang kosong" di akhir datafile (tabel demi tabel ... bahkan ketika Anda punya 200 tabel!?).

Maka Anda harus mengurangi ukuran datafile dengan "menebak" dengan seberapa banyak Anda dapat menguranginya, atau Anda harus tahu persis apa "ukuran blok" Anda ... Dan akhirnya Anda tidak boleh lupa untuk "membangun kembali indeks".

Lihat misalnya: http://asktom.oracle.com/pls/asktom/f?p=100:11~::::P11_QUESTION_ID:54178027703899

dan http://www.oracle-base.com/articles/misc/ReclaimingUnusedSpace.php

Apakah ada prosedur PL / SQL sederhana yang, diberikan nama tablespace atau nama datafile, akan melakukan pekerjaan itu? Atau alat Oracle serupa?


Info menarik: periksa apakah tablespace Anda "dikelola secara lokal" atau "direktori dikelola". Yang pertama tampaknya memiliki penanganan datafile "defragmenting" yang lebih baik. Lihat: orafaq.com/node/3
Frosty Z

Jawaban:


5

Jawaban singkatnya adalah Tidak . Sayangnya cara untuk melakukan ini di Oracle memang membutuhkan "tumpukan besar pertanyaan yang membosankan". Artikel yang Anda tautkan adalah beberapa informasi terbaik yang tersedia pada subjek. Filefile memang menjadi terfragmentasi, sehingga bahkan jika ruang kosong ada di bawah segmen tertinggi, Oracle tidak akan secara otomatis mengkonsolidasikannya ketika a RESIZEdilakukan.

Untuk "defragment" tablespace Anda perlu memindahkan segmen ini ke awal datafile daripada di akhir. Untuk tabel, ini adalah proses offline yang artinya tabel tidak akan tersedia saat perpindahan sedang berlangsung. Indeks dapat dipindahkan baik offline atau dengan Edisi Perusahaan mereka dapat dipindahkan online. Karena Anda memiliki jendela pemadaman, saya sarankan Anda mengikuti langkah-langkah ini.

A. Kecilkan datafile dengan ruang kosong di luar tanda air tinggi. Ini dapat dilakukan sebagai berikut (kueri mirip dengan prosedur Frosty Z):

SELECT ceil( blocks*(a.BlockSize)/1024/1024) "Current Size",
   ceil( (nvl(hwm,1)*(a.BlockSize))/1024/1024 ) "Smallest Poss.",
   ceil( blocks*(a.BlockSize)/1024/1024) -
   ceil( (nvl(hwm,1)*(a.BlockSize))/1024/1024 ) "Savings",
   'alter database datafile '''|| file_name || ''' resize ' || 
      ceil((nvl(hwm,1)*(a.BlockSize))/1024/1024/100)*100  || 'm;' "Command"
FROM (SELECT a.*, p.value BlockSize FROM dba_data_files a 
JOIN v$parameter p ON p.Name='db_block_size') a
LEFT JOIN (SELECT file_id, max(block_id+blocks-1) hwm FROM dba_extents GROUP BY file_id ) b
ON a.file_id = b.file_id
WHERE ceil( blocks*(a.BlockSize)/1024/1024) - ceil( (nvl(hwm,1)*(a.BlockSize))/1024/1024 ) 
   > 100 /* Minimum MB it must shrink by to be considered. */
ORDER BY "Savings" Desc;

B. Setelah mengecilkan hal-hal di atas tanda air tinggi, cari tahu tablespace apa yang masih akan mendapat manfaat dari memiliki segmen bergerak.

SELECT DISTINCT tablespace_name FROM
(      
    SELECT tablespace_name, block_id + blocks LastBlock,
       lead(block_id) OVER (PARTITION BY File_ID 
          ORDER BY tablespace_name, file_id, block_id) NextBlock
       FROM dba_free_space 
) WHERE LastBlock <> NextBlock AND NextBlock IS NOT NULL;

C. Untuk masing-masing tablespace ini tentukan segmen mana yang perlu dipindahkan. (Ganti PENGGUNA dengan nama tablespace Anda atau gabung dengan kueri sebelumnya)

SELECT distinct de.segment_name
FROM dba_extents de
JOIN
(
   SELECT tablespace_name, file_id, MIN(block_id) LowestFreeBlock
   FROM dba_free_space
   WHERE tablespace_name = 'USERS'
  GROUP BY tablespace_name, file_id
) dfs ON dfs.tablespace_name = de.tablespace_name AND dfs.file_id = de.file_id
WHERE de.tablespace_name = 'USERS'
AND de.block_id > dfs.LowestFreeBlock;

D. Pindahkan setiap tabel dan bangun kembali indeks dan statistik.

E. Ulangi langkah A.

Saya baru saja membangun sebagian besar pertanyaan ini, jadi Anda harus mengujinya secara menyeluruh sebelum digunakan. Saya kira Anda bisa membuat prosedur yang akan digunakan EXECUTE IMMEDIATEuntuk membuat pernyataan aktual untuk berjalan secara dinamis, tetapi karena permintaan akan menerima ORA-08103: Objek tidak lagi ada saat perpindahan sedang berlangsung, saya pikir yang terbaik adalah mengontrol proses itu secara manual bahkan jika itu berarti sedikit lebih banyak waktu / usaha.


3

Solusi sebagian yang terinspirasi dari halaman ini :

Itu tidak mengatur ulang ruang kosong tetapi secara otomatis mendeteksi ruang kosong yang tersedia di akhir datafile dan mencetak perintah 'RESIZE' yang tepat.

DECLARE
    BLKSIZE INTEGER;

BEGIN
    SELECT VALUE INTO BLKSIZE FROM V$PARAMETER WHERE NAME = 'db_block_size';

    FOR INDEX_ROW IN (
      SELECT 'ALTER DATABASE DATAFILE ''' || FILE_NAME || ''' RESIZE ' || CEIL( (NVL(HWM,1)*BLKSIZE)/1024/1024 ) || 'M;' SHRINK_DATAFILES FROM DBA_DATA_FILES DBADF,
            (SELECT FILE_ID, MAX(BLOCK_ID+BLOCKS-1) HWM FROM DBA_EXTENTS GROUP BY FILE_ID ) DBAFS
            WHERE DBADF.FILE_ID = DBAFS.FILE_ID(+) AND CEIL(BLOCKS*BLKSIZE/1024/1024)- CEIL((NVL(HWM,1)* BLKSIZE)/1024/1024 ) > 0
    ) LOOP
        DBMS_OUTPUT.PUT_LINE(INDEX_ROW.SHRINK_DATAFILES);
    END LOOP;
END;

2

Sebelum Anda mencoba mengecilkanfile data sama sekali, tanyakan pada diri Anda: Apakah Anda akan membuat segmen baru lagi di dalam tablespace terkait entah kapan dalam waktu yang tidak begitu lama? Jika ya, tidak ada gunanya menyusut. Ruang hanya akan digunakan kembali untuk segmen baru Anda dan Anda menyelamatkan diri dan sistem dengan banyak upaya dengan membiarkannya apa adanya.


2

Setelah berselancar di Google selama berhari-hari, saya telah menemukan contoh paling sederhana dan jelas untuk mendapatkan kembali ruang kosong di tablespace setelah dihapus. saya harap ini membantu

Tautan: http://www.dbforums.com/oracle/976248-how-reduce-tablespaces-used-space-after-delete-records-2.html

larutan:

ALTER TABLE MOVE demo

Mari kita buat tabel dengan 9999 baris di dalamnya, masing-masing berukuran sekitar 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.

Tabel memiliki 29 luasan yang dialokasikan, dengan total 14,6 juta:

SQL> select count(*), sum(bytes) from user_extents where segment_name='T';
COUNT(*) SUM(BYTES)
---------- ----------
29 14680064

Mari kita hapus SEMUA baris:

SQL> delete from t;
9999 rows deleted.
SQL> commit;
Commit complete.

Sekarang- "kejutan" - tabel masih menggunakan luasan yang sama:

SQL> select count(*), sum(bytes) from user_extents where segment_name='T';
COUNT(*) SUM(BYTES)
---------- ----------
29 14680064

Mengapa Karena bahkan jika Anda menghapus semua baris tabel, Tanda Air Tinggi tidak berkurang - tidak pernah menurun, untuk memungkinkan konkurensi maksimum (Oracle sangat serius dalam memaksimalkan konkurensi yaitu kinerja dan skalabilitas; itu adalah alasan utama di balik keberhasilannya dalam aplikasi Perusahaan).

Deallocating ruang yang tidak digunakan (= ruang di atas HWM) tidak banyak membantu (karena tidak ada banyak ruang yang tidak digunakan di atas HWM):

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

Sekarang, mari kita PINDAHKAN tabel, yang pada dasarnya berarti mengkloning tabel (termasuk pemicu, kendala, dan sebagainya), mentransfer baris, menjatuhkan tabel "lama" dan mengganti nama yang baru - semua dibuat oleh kernel, sehingga sangat aman bahkan dalam kasus kegagalan mesin / server:

SQL> alter table t move;
Table altered.

Sekarang, kita sekarang hanya memiliki alokasi awal:

SQL> select count(*), sum(bytes) from user_extents where segment_name='T';
COUNT(*) SUM(BYTES)
---------- ----------
1 65536

Peringatan: biasanya terjadi bahwa banyak / semua indeks di atas tabel tidak dapat digunakan setelah pindah (tidak dalam kasus ini tetapi saya menjalankan 9.2.0.4, rilis terbaru, yang mungkin telah mengoptimalkan proses jika tabel benar-benar kosong ):

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

Jika STATUS bukan VALID, Anda cukup membangun kembali secara manual indeks:

SQL> alter index SYS_C002573 rebuild;
Index altered.

Atau Anda dapat mengotomatiskan seluruh proses:

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;
/

Sebagai contoh, mari kita atur secara manual indeks ke 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 Alberto


1

Seperti yang dikatakan sebelumnya, Anda harus memindahkan semua 200+ tabel di tablespace tersebut untuk membebaskan sebagian ruang dalam datafile Anda dan kemudian mengubah ukuran untuk mendapatkan kembali ruang tersebut. Tetapi alih-alih menjalankan semua pertanyaan itu, manajer Perusahaan 12c melakukan tugas ini. Anda harus menavigasi ke Database Home> Storage> Tablespace. Pilih tablespace yang ingin Anda kerjakan dan klik Reorganisasi. Ini akan memberikan opsi untuk melihat pernyataan SQL yang akan dieksekusi. Anda dapat mengambil salinannya dan menjalankannya sendiri atau menjadwalkan pekerjaan di EM.

Ini benar-benar menciptakan tablespace lain, memindahkan semua objek ke tablespace baru, membangun kembali indeks dan menjatuhkan objek dari tablespace lama.

Ada beberapa kekurangan yang bisa saya pikirkan. Ini harus dilakukan pada jam-jam di luar jam sibuk jika tidak maka sumber daya akan sibuk. File data (bukan tablespace) akan memiliki "reorg" ditambahkan ke namanya, menjelang akhir.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.