Büyük hacimli verileri yükleme – Bulk insert 

Çok büyük hacimli tablolardan veri çekme ve yükleme, eğer kaynak tablo doğru partition yapısında ve doğru şekilde indekslenmemiş ise makinanın gücüne göre çok yavaş olabilir

 

Böyle bir durumda PL-SQL in çok önemli bir özelliği olan BULK COLLECT ifadesi kullanılarak yükleme yapılabilir. Bu  ifade ile birlikte INSET, UPDATE, MERGE ve DELETE ifadeleri kullanılabilir. Birçok başka kullanım şekli ve amacı da var ama biz kısıtlı olarak nasıl büyük hacimli verilerde performans sağladığıyla ilgileneceğiz

 

Tabii ki başka yollarla da performans artışı şağlanabilir. Mesela kaynak tablo üzerinde uygun şekilde  partition oluşturma ve indeksleme yapmak, sorguyu (mümkün ise) daha verimli hale getirmek, PL-SQL döngüsü ile veriyi parça parça çekmek, sorguya uygun hint yazmak , pipelined table functions ( türkçe önerisi olan?) veya bunları birlikte yapmak.

Fakat kaynak tablonun hacmi fiziksel hafızadan çok daha büyük olduğu bir durum düşünün. Veriyi tek bir set halinde çekmek ve işlemek diğer çalışanları da zor durumda bırakacaktır. BULK COLLECT ifadesi bu durum için iyi bir çözüm. Çünkü veriyi LIMIT ifadesi ile sınırlanan birden parçalar halinde çeker ve işler. Buna alternatif olarak kaynak tabloya partition eklenip gene PL-SQL döngüsü ile veriyi parça parça yükleyebilirsiniz. Fakat gene de her seferinde devasa bir tabloya filtre uygulamak zorunda kalırsınız.

Peki her seferinde veriyi filtrelemeden parçalar halinde işlemenin yolu yok mu? rownum kullanılamaz mı? Hayır.  Oracle, rownum değerini veri setini ürettikten sonra koyar. MySQL bilenler için garip bir eksiklik olarak görülebilir

 

Şimdi örneğimize geçelim. Örneğimiz oe.orders tablosundan dw.fct_orders tablosuna 10.000 er parçalar halinde veri yükleyecek

 

DECLARE
TYPE t_order_raw_data IS TABLE OF dw.fct_orders%ROWTYPE
INDEX BY BINARY_INTEGER;
l_order_raw_arr   t_order_raw_data;
l_chunk_size      NUMBER := 20000;
CURSOR order_raw_cur  IS
SELECT /*+ PARALLEL(f 16)*/
FROM oe.orders f;
BEGIN
OPEN order_raw_cur;  LOOP
FETCH order_raw_cur
BULK COLLECT INTO l_order_raw_arr
LIMIT l_chunk_size;
EXIT WHEN order_raw_cur%NOTFOUND;
FORALL i IN INDICES OF l_order_raw_arr SAVE EXCEPTIONS
INSERT INTO dw.fct_orders
VALUES l_order_raw_arr (i);

END LOOP;

   CLOSE order_raw_cur;
END;