Parametreli sorgu: tek doğru yol
Kullanıcı girdisini sorgu metnine birleştirmek, SQL injection açığının kaynağıdır. Bunun yerine sorgu bir kez yazılır, değerler parametre olarak ayrı gönderilir. Veritabanı parametreyi her zaman veri olarak görür, kod olarak çalıştırmaz.
# Yanlış (Python) — girdi sorguya birleştiriliyor
cur.execute("SELECT * FROM customers WHERE email = '" + email + "'")
# Doğru — parametre
cur.execute("SELECT * FROM customers WHERE email = %s", (email,))
// C# / ADO.NET
var cmd = new SqlCommand("SELECT * FROM customers WHERE email = @email", conn);
cmd.Parameters.AddWithValue("@email", email);
Parametreli sorguların bir faydası da plan önbelleğidir: aynı sorgu metni farklı değerlerle tekrar kullanılır.
ORM nedir?
Entity Framework, Hibernate, Django ORM, SQLAlchemy, Prisma gibi araçlar tabloları sınıflara eşler ve SQL'i senin yerine üretir. Hızlı geliştirme sağlar ama ürettiği SQL'i görmeden kullanmak performans sorunlarına yol açar. ORM kullanan iyi bir geliştirici, ürettiği SQL'i günlükte okuyabilir.
N+1 sorunu
Bir sayfada 50 müşteri ve her birinin sipariş sayısı gösterilecek. Saf bir ORM kodu önce müşterileri çeker (1 sorgu), sonra döngüde her müşteri için sipariş sayısını sorar (50 sorgu): toplam 51 sorgu. Her sorgu ağ gidiş-dönüşü demektir.
-- N+1: uygulama döngüsünde SELECT customer_id, first_name FROM customers WHERE segment = 'Premium'; SELECT COUNT(*) FROM orders WHERE customer_id = 3; SELECT COUNT(*) FROM orders WHERE customer_id = 7; -- ... müşteri sayısı kadar
-- Çözüm: tek sorgu
SELECT c.customer_id,
c.first_name,
COUNT(o.order_id) AS siparis_sayisi
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
WHERE c.segment = 'Premium'
GROUP BY c.customer_id, c.first_name;
ORM'lerde bunun karşılığı “eager loading”dir: Include() (EF), select_related / prefetch_related (Django), joinedload (SQLAlchemy).
Diğer iyi alışkanlıklar
- SELECT * yerine gereken sütunları iste; tablo genişledikçe uygulama sessizce yavaşlar.
- Bağlantı havuzu (connection pool) kullan; her istekte yeni bağlantı açmak pahalıdır.
- İşlemleri kısa tut; işlem açıkken dış servise HTTP isteği yapma.
- Sayfalama yap; bir listeye 100.000 satır çekme (sonraki ders).