Zaman zaman database’ de tablolara yüklü miktarda insert işlemleri olur. Özellikle bahsettiğimiz bir raporlama database’ ise bu işlem kaçınılmaz olur ve yapılan işlemin boyutu undo tablespace’ inizin boyutundan fazla olduğunda (undo tbs autoextend olmadığını varsayarsak) “ORA-30036: unable to extend segment by 8 in undo tablespace ‘UNDOTBS2’” hatasını almanız kaçınılmaz olacaktır. Ora-30036 hatasının önüne geçmek için yapılan insert işlemini parçalamak ve daha ufak bölümlerde yapmak sizin için kaçınılmaz bir çözüm olacaktır. Bu işlemi de yaparken tablo içerisindeki bir alana göre bir den fazla where conditionı ile sorgu yazmak yerine tek sorgu ile ama belirli sayıda data üzerinde sırayla işlem yaparak undo’ ya fazla yüklenmeden tabiri caizse patlatmadan işleminizi gerçekleştirebilirsiniz. Örnek olması açısından şöyle bir bilgi verebilirim, raporlama database’ lerimizden birinde yer alan 54 gb bir datayı farklı bir schema altına aşağıdaki script ile yaklaşık 1 saat gibi bir sürede taşımıştım. (Aşağıda belirtmiş olduğum tuning yöntemlerinden hiçbirini kullanmadan) Tabi bu süreyi etkileyen diğer faktörleride göz önünde bulundurmak lazım. (işlemin yapıldığı andaki database deki yoğunluk, kullanılan server’ ın kapasitesi, taşınan tablespace’ lere ait dbf’ ler üzerindeki o anki i/o durumu vs.)
Aşağıdaki scripti çalıştırmadan önce hangi tabloyu taşıtacak iseniz o tablonun DDL’ ini taşıyacağınız ortamda öncelikle çalıştırıp tabloyu boş olarak oluşturuyorsunuz. Sonrasında scriptin içerisindeki select ve insert kısımlarını bir sefere mahsus düzenlemeniz yeterli olacaktır.
DECLARE
v_time NUMBER;
BEGIN
DBMS_OUTPUT.put_line (‘Started’);
v_time := DBMS_UTILITY.get_time;
FOR r IN (SELECT ROWNUM, mesaj_no, islem_kodu, atm_kodu, kart_no,
son_kul_tar, mesaj_date, mesaj_time, stan, responce,
responce_detay, mesaj, tarih, saat
FROM atm_mesaj_log)
LOOP
INSERT INTO atm_mesaj_log_hist
(mesaj_no, islem_kodu, atm_kodu, kart_no,
son_kul_tar, mesaj_date, mesaj_time, stan,
responce, responce_detay, mesaj, tarih, saat
)
VALUES (r.mesaj_no, r.islem_kodu, r.atm_kodu, r.kart_no,
r.son_kul_tar, r.mesaj_date, r.mesaj_time, r.stan,
r.responce, r.responce_detay, r.mesaj, r.tarih, r.saat
);
IF (MOD (r.ROWNUM, 50000) = 0)
THEN
BEGIN
COMMIT;
DBMS_OUTPUT.put_line (‘commit executed’);
END;
END IF;
END LOOP;
DBMS_OUTPUT.put_line ( ‘time used: ‘
|| (DBMS_UTILITY.get_time – v_time) / 100
|| ‘ secs’
);
DBMS_OUTPUT.put_line (‘Finished’);
COMMIT;
END;
/
Scripte yer alan “IF (MOD (r.ROWNUM, 50000) = 0)” bu kısım kaç satırda bir commit işlemini gerçektireceğini belirttiğiniz kısımdır. Bu sayede milyonlarca kaydı bir seferde insert etmek yerine parça parça hata almadan (ki unutmayın database üzerinde çalışan tek kişi siz değilsiniz J) işleminizi tamamlayabilirsiniz.
Son ve önemli bir not, yukarıdaki script ile işleminize hız katmak istiyorsanız, aşağıdaki ufak tuning bilgileri işleminizi son derece kısaltacaktır.
– tablo üzerinde varsa indexleri aktarım öncesinde yaratmayın, insert işleminiz bittiksen sonra create edebilirsiniz.
– İnsert scriptine /*+ Append */ hintini mutlaka verin.
– Database’ iniz archive modda ama force logging modda değilse tablonun logging type’ ını işlem öncesinde NOLOGGING’ e alırsanız, işlem sırasında redoya hiçbir kayıt atmayacağından çok daha hızlı çalışacaktır. (işlem bittikden sonra tekrar logging moda alabilirsiniz.
Yukarıdaki scripti ve belirttiğim tuning metotlarını kullanarak benzer bir işlem yapan olursa deneyimlerini paylaşırsa bunuda burdan tüm arkadaşlara duyurmuş oluruz. En azından gerçekçi bir takım veriler üzerinden konuşuyor oluruz.
teşekkürler
Iyi bir baslangic
Teşekkürler