Oracle 11g Cursor kullanımı

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;
Share