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.
Ş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;
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;
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;
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 Parametresi: Bu 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;
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;
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.