Büyük tabloları silerken aşağıdaki yöntemi kullanırsanız UNDO TABLESPCADE'DEN Yer kazancı sağlarsınız ama performans acısından biraz geç bitecektir sorgunuz.
Nasıl çalıştığına kısaca değinmek gerekir ise undo segment commit yapılana kadar bütün tabloyu yada update ve delete işlemine maruz kalan kayıtları tutar. Buda bizim için büyük boyutlu tabloları silmede sorun oluşturur. Aşağıdaki yöntemde ise 1000 er 1000 er commit işlemi yaprak undo segment de yer kazancı sağlar. Bu değeri değiştirebiliriz. Tercih sizin.
Delete yönteminden daha iyi olan yöntem önce istenilen satırlar için tablonun yedeğini alma sonra truncate edip tablonun ismini değiştirmektir. Truncate delete denebilir (Aslında böyle bir isim üretmek lazım.) Bu yöntem veri ambarlarında (data warehouse) kullanılıyor.
SET timing on
--ne kadar sürede çalıştığını görek için bunu ekliyoruz.
DECLARE
v_count NUMBER := 0;
toplam NUMBER := 0;
--silinecek veriler için curcor tanımlayalım.
CURSOR del_record_cur
IS
SELECT ROWID
FROM sil_deneme;
--where ile istediğimiz koşulu burada girebiliriz.
--koşulsuz silmek biraz saçma olacaktır. TRUNCATE etmek gerekir.
BEGIN
FOR rec IN del_record_cur
LOOP
DELETE FROM sil_deneme
WHERE ROWID = rec.ROWID;
toplam := toplam + 1;
v_COUNT := v_COUNT + 1;
--burada kaç kayıt silindikten sonra commit yapılacağına kendiniz karar veriniz.
IF (v_COUNT >= 1000)
THEN
COMMIT;
v_COUNT := 0;
END IF;
END LOOP;
COMMIT;
DBMS_OUTPUT.put_line ( 'sil_deneme tablosundan '
|| toplam
|| ' kayıt silinmiştir'
);
END;
/
çalışma sürelerini değerlendirirsek.
sil_deneme tablosundan 928161 kayıt silinmiştir
Elapsed: 00:00:50.28
//////////////////////////////////////////////////
delete from sil_deneme
928161 rows deleted.
Elapsed: 00:00:25.18
Bazı arkadaşlarımız data warehouse'da delete işlemine kesinlikle karşı çıkacaklardır. Haklılarda. Ama şu şekilde bir durum oluştuğunda ne olacak.
400.000.000 kayıtlı bir tablom var vebu tabloda 10 milyon kayıt yanlış girilmiş. Bende bu 10 milyon kaydı silmeliyim. 10 milyon kayıt için tabloyu swap'lamakda
o kadar akılcı gelmiyor bana bu şekilde parça parça delete işlemi yapılabilinir.
bir diğer yöntem ise ki bu bence daha güzel.
DECLARE
BEGIN
--10 milyon kaydi birer milyon birer milyon silecegimiz için 10 defa döngüye soktum
--Bu örneği diğer örnekten hızlı yapan yönu ile birer birer silmesi değil toplu olarak silmesidir.
--bu esnada paralellik hint'i verilerecek
--ciddi zaman kazancı sağlayabilirsiniz.
FOR i IN 1 .. 10
LOOP
DELETE FROM delete_deneme
WHERE acoount_id > 345000
--silinecek olan kayıtları belirledikten sonra rownum ile birer milyonluk siliyorum.
AND ROWNUM <1000000
--her 1 milyon kayitta bir commit yapiyorum.
--undo segment dolmuyor :))
COMMIT;
END LOOP;
--bu commit de benden olsun
COMMIT;
END;
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment