Merhabalar,
Geçenlerde Oracle 11g’de üç çeşit cursor’ın karşılaştırmalı performans sınamasını gerçekleştirdim. Aslında iş için gerekti ama fırsattan istifade sizlerle de paylaşmak istedim. Bu aralar aktif şekilde blog yazımı ile ilgilenmesem de buna benzer fırsatları değerlendirmek gerekli :)
3,629,848 adet kayıt için 11g’de performans değerleri aşağıdaki gibidir;
1- Cursor ve Bulk Collect (Open / Fetch Bulk limit 10000 / Close) ~2,5sn – belirlenmiş memory kullanımı.
Start:34.26.163863000 PM +03:00
End: 34.28.616085000 PM +03:00
2- Sadece Implicit (For) Cursor ~4,5sn – düşük memory kullanımı (1. maddenin limit 100 ile kullanımı kadar)
Start: 33.22.212231000 PM +03:00
End: 33.26.701057000 PM +03:00
3- Eski tarz (Open / Fetch / Close) Cursor ~50sn – çok düşük memory kullanımı
Start: 27.52.405369000 PM +03:00
End: 28.42.254359000 PM +03:00
1. madde ile 2. madde arasındaki fark tamamen “limit 10000” den kaynaklanıyor. 2. Madde için oracle sistemi varsayılan olarak 100 değerini kullanıyor. Bu nedenle 2.nin memory kullanımı 1.ye gÖre daha az olduğu yÖnünde genel bir kabul mevcut.
Kolay gelsin.
Kodlar;
1- Cursor ve Bulk Collect (Open / Fetch Bulk limit 10000 / Close) ~2,5sn
DECLARE v_total NUMBER; TYPE number_array IS TABLE OF NUMBER INDEX BY BINARY_INTEGER; t_upd number_array; CURSOR c1 IS SELECT second_price FROM basic_tariff_price; BEGIN v_total := 0; DBMS_OUTPUT.put_line ('Start:' || SYSTIMESTAMP); OPEN c1; LOOP FETCH c1 BULK COLLECT INTO t_upd LIMIT 10000; FOR v_index IN 1 .. t_upd.COUNT LOOP IF t_upd (v_index) IS NOT NULL THEN v_total := v_total + t_upd (v_index); END IF; END LOOP; EXIT WHEN c1%NOTFOUND; END LOOP; CLOSE c1; DBMS_OUTPUT.put_line ('Toplam: ' || v_total || ', ' || SYSTIMESTAMP); EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.put_line (SQLERRM); WHEN OTHERS THEN DBMS_OUTPUT.put_line (SQLERRM); END;
2- Sadece Implicit (For) Cursor ~4,5sn
DECLARE v_total NUMBER; BEGIN v_total := 0; DBMS_OUTPUT.put_line ('Start:' || SYSTIMESTAMP); FOR cur IN (SELECT second_price FROM basic_tariff_price) LOOP IF cur.second_price IS NOT NULL THEN v_total := v_total + cur.second_price; END IF; END LOOP; DBMS_OUTPUT.put_line ('Toplam: ' || v_total || ', ' || SYSTIMESTAMP); EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.put_line (SQLERRM); WHEN OTHERS THEN DBMS_OUTPUT.put_line (SQLERRM); END;
3- Eski tarz (Open / Fetch / Close) Cursor ~ 50sn
DECLARE v_total NUMBER; v_upd_rec NUMBER; CURSOR c1 IS SELECT second_price FROM basic_tariff_price; BEGIN v_total := 0; DBMS_OUTPUT.put_line ('Start:' || SYSTIMESTAMP); OPEN c1; LOOP FETCH c1 INTO v_upd_rec; IF v_upd_rec IS NOT NULL THEN v_total := v_total + v_upd_rec; END IF; EXIT WHEN c1%NOTFOUND; END LOOP; CLOSE c1; DBMS_OUTPUT.put_line ('Toplam: ' || v_total || ', ' || SYSTIMESTAMP); EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.put_line (SQLERRM); WHEN OTHERS THEN DBMS_OUTPUT.put_line (SQLERRM); END;