Oracle BULK Update/Delete islemleri
Oracle veritabaniniz da çok büyük tablolarda veri silmeniz/güncellemeniz gerekirse ihtiyaç duyacaginiz en önemli sey yüksek performanstir. Özellikle SOA veritabani yönetenlerin yasadiklari en büyük sorun çok yavas silme islemleridir. Tablolar sürekli büyür ve soa purge islemi yetersiz kalir. Sizde mecburen daha çok veri silmek için yöntemler düsünürsünüz. Iste bu durumda neredeyse herkes bulk islemlere yönelir ve bulk delete ile verilerini temizler. Bulk islemleri bir örnekle anlatmak istiyorum. Içine su doldurmaniz gereken büyük bir bidonunuz olsun bu bidonu sahil kenarina götürüp içine su dolduracaksiniz bidonunuzu denizden bardakla doldurmak normal islemdir fakat kovayla bidonu doldurmak bulk operasyondur. Kovayla hem daha kisa zamanda doldurursunuz hemde daha az yorulursunuz fakat bardakla doldurmak hem çok zaman alir hem de sizi ciddi manada yorar. Bu yüzden normal silme islemi büyük verilerde her zaman sorun olmustur. Tabiki operasyonunuz bulk isleme çevrilebilir bir operasyon olmalidir aksi taktirde bazi mantiksal operasyonlar bulk a çevrilemez böyle durumlarda beklemekten baska çareniz kalmaz.
BULK DELETE
.Asagida örnegini verdigim bulk silme isleminizi kendi sorgunuza göre düzenleyebilirsiniz. Açiklamalari kodun içinde yapacagim.
CREATEORREPLACEPROCEDURE dlv_message_sil(prm_tarih DATE) --silinecek veriler tarihe göre seçildigi için tarih parametresi eklendi IS TYPE t_id_list ISTABLEOFROWID; -- tabloda verileri rowid ye göre silecegiz ve rowid leri --tutmak için tanimlayacagimiz degiskene verecegimiz veri tipi lBulkSize NUMBERDEFAULT50000; --kayitlari kaçar kaçar silecegiz kovanin büyüklügünü burada --belirlemis oluyoruz id_list t_id_list; -- yukarida tanimladigimiz tipi bir degisikene atadik. CURSOR c_dvl_message ( --- bu cursor ile silecegimiz kayitlarinin tümünü bir defalik çekiyoruz p_tarih DATE) IS SELECT/*+ parallel(t,16) */ t.ROWID FROM ttoprod_soainfra.dlv_message t where trunc(receive_date) <trunc(p_tarih); BEGIN OPEN c_dvl_message (prm_tarih); -- cursoru çagirip kayitlari topluyoruz LOOP FETCH c_dvl_message -- belirledigimiz limit kadar kayidi toplayip id_list --degiskenine aliyoruz BULKCOLLECTINTO id_list LIMIT lBulkSize; EXITWHEN id_list.COUNT=0; -- id_list e atilacak kayit kalmadiginda yani tüm kayitlar --bittiginde loop dan çikiyoruz FORALL indx IN id_list.FIRST.. id_list.LAST -- id_list içindeki kayitlari siliyoruz DELETEFROM ttoprod_soainfra.dlv_message t WHEREt.ROWID= id_list (indx); COMMIT; ENDLOOP; CLOSE c_dvl_message; -- silme islemi bittigi için cursor i kapatiyoruz EXCEPTION WHENOTHERS THEN ROLLBACK; executeimmediate'insert into hatalar values('''SQLERRM''')'; --eger hata alirsa hatalar tablosuna kayit atiyoruz. COMMIT; END;
BULK DELETE
.DECLARE lBulkSize NUMBERDEFAULT5000; -- ne kadar datayi ayni anda update edecegimiz CURSOR c_data --- update edecegimiz verileri topluyoruz IS SELECT /*+ parallel(t1,8) parallel(t2,8) */ COUNT(1)AS coun, SUM(t1.alan2) tutar, t1.alan1 anahtar FROM TEST1 t1, TEST2 t2 WHERE t1.id=t2.id GROUPBY t1.alan1; TYPE t_num_array ISTABLEOFNUMBER INDEXBYBINARY_INTEGER; -- toplayadigimiz verileri atacagimiz degisken için veri tipi TYPE t_char_array ISTABLEOFVARCHAR2(100) -- toplayadigimiz verileri atacagimiz degisken için veri tipi INDEXBYBINARY_INTEGER; deger1 t_num_array; -- verileri atacagimiz degiskeni tanimliyoruz deger2 t_num_array; -- verileri atacagimiz degiskeni tanimliyoruz deger3 t_num_array; -- verileri atacagimiz degiskeni tanimliyoruz BEGIN OPEN c_data;--verileri toplamak için cursor i açiyoruz LOOP FETCH c_data -- yukarda topladigimiz verileri belirledigimiz miktarda --degiskenlere atiyoruz BULKCOLLECTINTO deger1, deger2, deger3 LIMIT lBulkSize; EXITWHEN deger3.COUNT=0; --deger3 anahtar oldugu için onu seçtim ve veri bitince döngüden --çikmasini sagladim FORALL i IN1.. deger3.COUNT -- kayitlari güncelliyoruz UPDATE guncellenecek_tablo t1 SET t1.guncel1 = deger1(i) , t1.guncel2 = deger2(i) WHERE t1.id= deger3(i); COMMIT; ENDLOOP; -- buraya exception koyup hatalar kayit altina --alinabilir. yukaridaki örnekten alabilirsiniz DBMS_OUTPUT.put_line ('islem basarili'); CLOSE c_data;--- cursor u kapatmayi unutmuyoruz END;.