Özet: Doğru ve performanslı sorgu(SQL) yazmanın ipuçları ve dikkat edilmesi gereken noktalar anlatılıyor.

Yazılan sql’lerin sadece istediğimiz sonucu veriyor olması yetmez, aynı zamanda iyi performans gösteriyor olması lazım. Yani sorunlu sql’ler veritabanımızda çok fazla kaynak tüketebileceği gibi çok uzun sürelerde çalışır, hatta bir türlü bitmez.

Eğer bu tarz birkaç sorunlu sql çok maliyetli olup aynı zaman diliminde çalışıyorsa, veritabanı kaynak sıkıntısından dolayı yeni gelecek session’lara cevap veremez duruma gelebilir.

Veritabanının sağlığı, stabil çalışabilmesi açısından sürekli olarak sql’ler izlenmeli, sorunlu olan sql’ler tespit edilip müdahale edilmelidir. Bu anlamda ilk olarak sql’i yazan yazılımcının(developer) performanslı sql yazma konusunda dikkat etmesi önemlidir!

Sql’in çalışma performansı, Dev/Test/Prelive ortamlarda test edilmeden Prod (Üretim-Canlı) ortama alınmamalıdır!
SQL Performanslarında Dikkat Edilmesi Gerekenler” başlığı ile seri olarak blog yazılarımızı paylaşıyor olacağız.
Bu ilk seride aşağıdaki doğru/yanlış sql örneklerini inceleyelim:
1- a) daki kullanımda tablodaki tüm kayıtların ortalaması alınıp daha sonra koşul kullanılıyor ancak b) deki
kullanımda belli bir koşuldaki kayıtların sadece ortalaması alınıyor. Dolayısıyla b) deki doğrudur.

a) -> YANLIŞ KULLANIM

SELECT product_type_id,
 AVG(price)
 FROM products
 GROUP BY product_type_id
 HAVING product_type_id IN ( 1, 2 );

b) -> DOĞRU KULLANIM

SELECT product_type_id,
 AVG(price)
 FROM products
 WHERE product_type_id IN ( 1, 2 )
 GROUP BY product_type_id;

2- Sorgu sonucu tekrarlı olanları görüntülememek için “DISTINCT” kullanılır.
“EXISTS” ise bir alt sorguda gelen kayıtlar içinde istenilenlerin olup olmadığını kontrol eder.
DISTINCT, gelen sonuçlarda tekrarlı olanları belirlemeden önce sıralama yaptığıdan verimsizdir ve bu yüzden de EXISTS tercih edilmelidir.

a) -> YANLIŞ KULLANIM

SELECT DISTINCT product_id, name
 FROM products a, purchase b
 WHERE a.product_id = b.product_id;

b) -> DOĞRU KULLANIM

SELECT product_id, name
 FROM products a
 WHERE EXISTS
 (SELECT 1
 FROM purchase b
 WHERE a.product_id = b.product_id);

3- a) daki kullanımda tablonun “kart_no” kolonundaki tüm kayıtlarını şifreleyip daha sonra değerimizle eşitleniyor, b) deki kullanımda ise olması gerektiği gibi değerimizi şifreledikten sonra tabloda aratıyoruz

a) -> YANLIŞ KULLANIM

select * from onemli_tablo where enc_dec_pkg.get_enc_val(kart_no)='10000000000000002';

b) -> DOĞRU KULLANIM

select * from onemli_tablo where kart_no=enc_dec_pkg.get_enc_val('10000000000000002');

4- Aşağıdaki “NOT”, “!=”, “<>”, “TRUNC”, “SUBSTR”, “||(concatenate)” kullanım örnekleri index kullanımını iptal edeceği için dikkat edilmeli!

a) -> Önerilmez

WHERE account != '0'

b) -> Önerilir

WHERE account > '0'

———————————————–

a) -> Önerilmez

WHERE TRUNC(tarih) = TRUNC(sysdate)

b) -> Önerilir

WHERE tarih BETWEEN TRUNC(sysdate) AND TRUNC(sysdate) + 1

———————————————–

a) -> Önerilmez

WHERE SUBSTR(name,1,5) = 'ahmet'

b) -> Önerilir

WHERE name LIKE 'ahmet%'

———————————————–

a) -> Önerilmez

WHERE name || surname = 'ahmet'

b) -> Önerilir

WHERE name = 'ahmet' AND surname = 'bulut'

———————————————–

* Kolon eşitliğin her iki tarafında da kullanılırsa index kullanımı iptal olur

a) -> Önerilmez

WHERE name = NVL (a_name, name)

b) -> Önerilir

WHERE name LIKE NVL (a_name, '%')