Oracle’ da Shrink Operasyonu Nedir / Nasıl Yapılır …

Veritanımızdaki objeler zaman içerisinde tablo üzerinde sürekli olarak delete – insert – … işlemlerinin yapılmasından dolayı fragmantasyona uğrayıp aslında olması gereken size’ larından çok daha fazla yer işgal eder duruma gelebilirler. Bu tarz operasyonlarda bilinen en büyük yanlışlık tablodaki eski verileri belirli kritere göre silmeme rağmen neden bu tablo sürekli olarak büyüyor ? şeklindeki itirazlardır. Özellikle dba’ lerin zaman zaman tablolarda oluşan fragmantasyonları yazılımcılara bildirdiklerinde ve bunun için çözüm üretmeye çalıştıklarında sıklıkla aldıkları cevap ; biz tabloda zaten X günlük veri tutuyoruz neden büyüyor şeklinde oluyor şeklindeki dönüşlerdir. Delete işlemi tabloya yer kazandırmaz, oracle daki segment büyüme mantığı kullanılan blogun delete ile silinse dahi tekrar kullanılmadan bir sonraki blok üzerinden devam etme mantığına dayanır. (delete blok üzerindeki high water mark’ ı geri çekmez) Bu durumu bir örnekle açıklayıp tabloya orijinal size’ ını nasıl kazandırabileceğimizden bahsedelim.

— öncelikle test tablomuzu oluşturup tablo üzerinde delete – insert – … işlemleri ile tablo üzerinde fragmantasyon oluşmasını sağlamaya çalışalım ;

SQL> create table test as select * from dba_objects
Table created.

SQL> insert into test select * from test
69488 rows created.

SQL> commit
Commit complete.

SQL> insert into test select * from test
138976 rows created.

SQL> commit
Commit complete.

SQL> insert into test select * from test
277952 rows created.

SQL> commit
Commit complete.

SQL> insert into test select * from test
555904 rows created.

SQL> commit
Commit complete.

SQL> analyze table test estimate statistics
Table analyzed.

Tablodaki kayıt sayısını kontrol edelim;

SQL> select count(*) from test

COUNT(*)
———-
1.111.808
1 row selected.

Şu anki durumdaki size’ ına bakalım;

SQL> select segment_name, bytes/1024/1024 mb from dba_segments where segment_name = ‘TEST’

SEGMENT_NAME MB
———————– ———-
TEST 128
1 row selected.

1.1 milyon adet datammızın şu anki toplam size’ i 128 MB devam edelim;

SQL> delete test where rownum < 500000 499999 rows deleted. SQL> insert into test select * from test
611809 rows created.

SQL> commit
Commit complete.

SQL> delete test where rownum < 500000 499999 rows deleted. SQL> commit
Commit complete.

SQL> insert into test select * from test
723619 rows created.

SQL> commit
Commit complete.

SQL> analyze table test estimate statistics
Table analyzed.

Yine bir miktar ekleyip çıkarma işleminden son durumdaki datamızı count edelim;

SQL> select count(*) from test

COUNT(*)
———-
1.447.238
1 row selected.

Son durumdaki size’ ına bakalım ;

SQL> select segment_name, bytes/1024/1024 mb from dba_segments where segment_name = ‘TEST’

SEGMENT_NAME MB
———————— —–
TEST 232
1 row selected.

Toplam data büyüklüğümüz 1.4 milyona ulaşmış, tablomuzun size’ i ise 232 MB olmuş. Dikkat ederseniz data miktarı % 27 büyürken tablonun toplam size’ indaki artış % 80 lerde gerçekleşmiş. Devam edelim;

SQL> delete test where rownum < 500000 499999 rows deleted. SQL> insert into test select * from test
947239 rows created.

SQL> commit
Commit complete.

Tablodaki tüm datayı siliyoruz;

SQL> delete test
1894478 rows deleted.

SQL> commit
Commit complete.

SQL> analyze table test estimate statistics
Table analyzed.

Tüm datanın silindiğini teyit edelim;

SQL> select count(*) from test

COUNT(*)
———-
0
1 row selected.

Tablomuzda hiçbir kayıt yokken tablonun size’ i 232 MB olarak kaldı.

SQL> select segment_name, bytes/1024/1024 mb from dba_segments where segment_name = ‘TEST’

SEGMENT_NAME MB
———————– —-
TEST 232
1 row selected.

İşte anlatılmak istenen durumda tam bu idi. Tabloda yer kazanmak istiyorsanız yapmanız gereken işlem delete değil truncate veya drop – create gibi yöntemler olmalıdır. Uygulamanızın yapısı gereği drop – create veya truncate – insert gibi yöntemleri kullanamıyorsanız o zaman tablonuz üzerinde belirli dönemlerde oluşan bu tarz fragmantasyonları gidermek için shrink, export – import, move table – rebuild index vs … gibi yöntemlere başvurmanız gerekecektir. Daha önce tabloların move edilip sonrasında indexlerin nasıl rebuild edilmesi gerektiğinden bahsetmiştim. (http://www.kamilturkyilmaz.com/2010/10/25/tablo-ve-indexlerin-tasinmasi/ )
Aynı şekilde tablolar üzerindeki lob ssegmentler üzerinde move rebuild işlemlerinin nasıl yapılması gerektğindede http://www.kamilturkyilmaz.com/2011/02/25/lobindex-ve-lobsegment%E2%80%99-lerin-create-move-rebuild-edilmesi/ başlıklı yazımda değinmiştim.

Bugün shrink işleminden bahsetmek istiyorum ;

Shrink işlemi tablonun kullanmış olduğu blokları reorganize ederek dağınıklığı gideren dolayısıylada olması gerektiği kadar blok kullanılmasını sağlayarak disk üzerinde yer kazanmanızıda sağlayan bir işlem olarak tanımlayabiliriz ;

Nasıl yapacağımız ile ilgili olarak ;

Shrink işlemi datanın fiziki olarak da yerini (yer aldığı blok’ u değiştirdiğinden) değiştirdiğinden dolayı tablonun row movement özelliğini öncelikle enable etmemiz gerekiyor;

SQL> alter table test enable row movement
Table altered.

Tablolardaki fragmantasyonu saptamak için kolaylık olması açısından aşağıdaki sql’ ide kullanabilrisiniz ;

SELECT DISTINCT owner ownr,
‘Alter table ‘ || owner ||’.’|| segment_name || ‘ shrink space cascade;’ seg_name,
segment_type seg_type,
tablespace_name tbs_name,
file_id dbf_number
FROM dba_extents
WHERE ( (block_id + 1)
* (SELECT VALUE
FROM v$parameter
WHERE UPPER (name) = ‘DB_BLOCK_SIZE’) + BYTES) > (10000 * 1024 * 1024)
and segment_type = ‘TABLE’
and owner = ‘KAMIL’

OWNR SEG_NAME SEG_TYPE TBS_NAME DBF_NUMBER
KAMIL Alter table KAMIL.TEST shrink space cascade; TABLE DATA 1

SQL> alter table kamil.test shrink space cascade
Table altered.

Tabloyu shrink ettikden sonra size’ ini tekrar kontrol edelim;

SQL> analyze table test estimate statistics
Table analyzed.

SQL> select segment_name, bytes/1024/1024 mb from dba_segments where segment_name = ‘TEST’

SEGMENT_NAME MB
———————– ——–
TEST 0
1 row selected.

SQL> alter table test disable row movement
Table altered.

Shrink işlemi ile ilgili önemli bir not;

Compress tablo üzerinde shrink işlemi yapamazsınız, compress şeklinde kullanmakta olduğunuz tablolarınız var ise bunlarda shrink işlemi yapmak istiyorsanız öncelikle tabloyu nocompress edip shrink işleminden sonra tekrar compress hale getirerek yapmalısınız ;

SQL> alter table kamil.test compress
Table altered.

SQL> alter table test enable row movement
Table altered.

Shrink etmeye çalışalım ;

SQL> alter table kamil.test shrink space cascade
alter table kamil.test shrink space cascade
Error at line 1
ORA-10635: Invalid segment or tablespace type

Compress moddan çıkartıp tekrar deneyelim ;

SQL> alter table kamil.test nocompress
Table altered.

SQL> alter table kamil.test shrink space cascade
Table altered.

SQL> alter table kamil.test compress
Table altered.

Shrink işlemi ile ile unutulmaması gereken bir noktada, shrink işlemi yapılırken tablo locklı olarak üzerinde işlem yapılacağından dolayı işlem bitene kadar tabloya erişimin olmaması gerekmektedir.

Tablo üzerinde istemiş olduğumuz küçülmeyi sağlamış bulunuyoruz. Bir sonraki yazımda lob segmentler üzerinde nasıl shrink yapabiliriz den bahseteceğim.

Be Sociable, Share!

One comment

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir


3 + = altı