3 Ekim 2012 Çarşamba

Oracle’da Prosedürel Parametreler

 Oracle’da Prosedürel Parametreler ve NOCOPY Deyimi

Herkese Selam,
Bugün sizlere Oracle’da genellikle fonksiyon ve prosedürlerde sık olarak kullandığımız parametre tiplerinden, bunların davranış biçimlerinden ve bunlara bağlı olarak NOCOPY deyiminin ne olduğundan ve etkilerinin neler olabileceğinden bahsedeceğim.
Parametre Tipleri 
Oracle’da kullandığımız prosedürel parametre tipleri 3 tanedir. Bunlar IN, OUT ve IN OUT‘dur. Bu parametrelerin nasıl tanımlanacağı söz deyim olarak aşağıda gösterilmiştir.

CREATE PROCEDURE tmp (x IN NUMBER, y IN OUT VARCHAR2, z OUT VARCHAR2) IS BEGIN NULL; END;

Şimdi kısaca bu parametre tiplerini kısaca açıklayalım. 
IN Paramteresi: Bu parametre tipi Oracle tarafından default olarak belirlenmiş parametre tipidir. Prosedür ve fonksiyon yazarken yukarıda bahs ettiğimiz  parametre söz deyimlerinden herhangi birini özellikle belirtmediğimiz sürece Oracle parametremiIN olarak tanımlar. Pass by Reference mantığına göre çalışmaktadır. Yani IN parametresi alan bir prosedür’ü çağırdığımızda, IN parametresine gönderdiğimiz değişkenin yada değerin yalnızca memory’deki adresi prosedüre gönderilir. IN parametresinin en önemli özelliği ise Read Only olmasıdır. Prosedüre gönderdiğimiz değer eğer IN tipinde ise bu değer prosedür içinde yalnızca okunabilir. Üzerinde değişiklik yapılamaz. Üzerinde değişiklik yapıldığı takdirde compile-time ‘de hata alınır.

Örnek Çağırım: 
CREATE PROCEDURE tmp_2 (x IN NUMBER, y IN VARCHAR2)
IS
sonuc NUMBER := 0;
BEGIN
sonuc := x + y;
END;
—Çağırma Kısmı
EXEC tmp_2(10,20);
Out Parametresi: OUT parametresi, isiminden’de anlaşılabileceği gibi, prosedür veya fonksiyonda OUT olarak tanımlanmış parametreyi, ilgili prosedür veya fonksyonu çağıran alt programa geri gönderen parametre yapısıdır. Kullanımı oldukca sıktır çünkü bize fonksiyon ve prosedürlerden geriye birden fazla değer döndürmemizi sağlamaktadır. Çalışma yapısı pass by value dur.
Örnek: 
CREATE PROCEDURE tmp_2 (p_x IN NUMBER, p_y IN VARCHAR2, p_z OUT VARCHAR2)
IS
BEGIN
p_z := p_x + p_y;
END;
—Çağırma Kısmı
DECLARE
v_sonuc NUMBER := NULL;
BEGIN
tmp_2 (10, 20, v_sonuc);
DBMS_OUTPUT.put_line (v_sonuc);
END;
Yukarıdaki örnekte çağırma kısmından’da göreceğimiz gibi null olarak yollanan değerin(v_sonuc) prosedür içinde dolup çağırılan yere geri döndürülmesi ile değer console’a yazılmıştır. Burada ilgi çekici bir diğer noktada bu değerin dolup geri dönmesine karşın dolduğu prosedürde herhangi bir return söz deyimi kullanmayışımızdır. Unutmamalıdırki daha öncede bahse ettiğimiz gibi fonksiyon ve prosedürlerden bu yöntem sayesinde birden fazla değer geriye döndürülebilmektedir.
IN OUT ParametresiBu parametrenin çalışma yapısı pass by value’dur. IN OUT olarak tanımlanan parametre aslında hem IN hemde OUT parametre tipinin özelliğini ortak barındırır. IN paramtresinin yalnızca Read Only olduğundan bahs etmiştik bu yüzden üzerinde değişiklik yapıldığı takdirde compile time da hata alınacağını söylemiştik fakat bu durum IN OUT tanımlanan  parametreler için geçerli olmamaktadır. Bu tip parametrelerin hem değerleri üstünde değişiklik yapılabilemektedir hemde değiştirilen değerin son hali geriye döndürülebilmektedir.
Örnek:
CREATE OR REPLACE FUNCTION add_x_y (p_x IN NUMBER, p_y IN NUMBER, p_result IN OUT NUMBER)
RETURN NUMBER
IS
BEGIN
p_result := p_x + p_y;
RETURN 1;
END;
DECLARE
v_a NUMBER;
v_result NUMBER:=150;
BEGIN
v_a := add_x_y (10, 20, v_result);
DBMS_OUTPUT.put_line (‘Result: ‘ || v_a || ‘ Sonuc: ‘ || v_result);
END;
Yukarıda Parametreleri ve çalışma mekanizmalarından bahs ettik. Şimdi bu parametrelerin oluşturabileceği performans problemlerine karşı yazılabilecek NOCOPYhint’inden bahs edeceğim.

NOCOPY Hint’nin Kullanımı
PL/SQL ‘de 3 tip parametre kullanıldığını yukarıda ayrıntılı bir şekilde açıkladık. IN-OUT-IN OUT.  Bu parametre tiplerinden OUT ve IN OUT’un pass by value mantığında çalıştığından  bahs ettik. Bu konuyu biraz daha açıcak olursak pass by value yönteminde ilgili prosedür veya fonksiyona gönderilecek değer ilgili fonksiyon ve prosedürün kullanımı için memory’de başka bir alana kopyalanmaktadır.  İşte bu konu ile ilgili performans handikapları bu noktada başlamaktadır. Eğer gönderdiğimiz parametre büyük bir collection(array), record veya büyük boyutlu objeler ise bu değişkenlerin memory’de başka bir alana kopyalanmaları oldukça uzun sürecektir. Buda sorgu zamanlarımızı olumsuz yönde etkileyecektir.  Execution Time’mımız ve memory kullanımımız artacaktır. Bu handikap’ı engellemek için NOCOPY hintini OUT ve IN OUT parametreleri için kullanabilmekteyiz. Bu hinti ilgili parametrelerin yanına yazdığımız takdirde paramterenin çalışma yapısı pass by value’dan pass by reference’a dönecektir. Yani değişkenin içeriği kopyalanmaktansa, memory’deki adresi ilgili fonksiyon veya prosedüre gönderilecektir.
Örnek Tanımlama: 
CREATE OR REPLACE FUNCTION add_x_y (p_x IN NUMBER, p_y IN NUMBER, p_result IN OUT NOCOPY NUMBER)
RETURN NUMBER
IS
BEGIN
p_result := p_x + p_y;
RETURN 1;
END;

NOCOPY Hint’nin Olası Etkileri
NOCOPY kullanmadığımız bir case düşünelim. NOCOPY hinti kullanmadığımız için out ve in out paramterelerinin default olarak  pass by value mantığına göre çalışacağını biliyoruz. Bu case’de ilgili prosedür ve fonksiyonu çağıran alt programda, fonksiyon veya prosedürden döndüldükten sonra beklenmeyen veya handle edilmemiş bir exception dan kaynaklı çalışmanın durdurulduğunu varsayalım. Bu durumda kullanılan parametreler memory’de başka bir alana kopyalanıp değiştirildiğinden ötürü (yani orjinal hallerinin hala durmakta) işlemlerin ROLLBACK edilmesi mümkün olabilecektir. Bunun tam tersi bir durum oluştuğunu düşündüğümüz takdirde(NOCOPY hinti kullanacağımız durum), çalışma mekanizmasının pass by refrence’a döneceğinden ötürü değerlerin memory’de tek bir yerde duracağı ve değişikliklerin yalnızca burada yapılacağı aşikardır. Bu case’de de ilgili prosedür ve fonksiyonu çağıran alt programda, fonksiyon veya prosedürden döndüldükten sonra beklenmeyen veya handle edilmemiş bir exception dan kaynaklı çalışmanın durdurulduğunu varsayalım, işte bu sefer değişken memory’de tek bir kopya olduğundan ve muhtemelen orjinal kopyasının değişmesinden dolayı işlem ROLLBACK edilemeyecektir. Bu durumdan’da anlaşılacağı gibi kontrollü bir Exception Handling yaptığımız zaman NOCOPY hintinden pozitf anlamda faydalanmamız mümkün olacaktır. Aksi takdirde işlemlerimizi rollback etmek pek mümkün olamayacaktır.
Brr diğer etki ise Remote Procedure Call(RPC) işlemlerinde karşımıza çıkmaktadır. Uzak prosedür çağırımları yapıları gereği yalnızca pass by value mantığı üzerine çalıştıklarından dolayı  yazılan NOCOPY hinti çalışmayacaktır. Bu sebepten dolayı RPC  işlerinde NOCOPY kaynaklı performans iyileşmesi beklenmemelidir.
NOCOPY’nin Yoksayılacağı Durumlar
Aşağıda listelenecek durumlar oluştuğunda NOCOPY hinti ignore edilir.
1- Gerçek parametre bir tabloya ait  index bileşeni ise,
2- Gerçek parametre NOT NULL olarak işaretlenmiş bir constrainted ise,
3- Gerçek parametre %ROWTYPE veya %TYPE tipinde tanımlanmış Recordlar’dan oluşuyor ve kayıtlarla ilgili kısıtlamalar farklı ise,
4- Implicit bir data tipi dönüşümü gerekli ise,
5- External veya Remote procedure call yapılıyor ise,
NOCOPY Hinti ignore edilir.