Bilgi Bankası
GenelPerformans ve kapasite 15 dk 14.06.2026

ORM kaynaklı veritabanı sorunları: N+1 sorgu, gereksiz transaction ve eksik indeks

ORM kötü değildir; ama veritabanını görünmez yaparsa sorun çıkarır. N+1 sorgu, gereksiz transaction, eksik indeks ve kontrolsüz eager loading üretimde “veritabanı yavaş” diye görünür.

Bu yazı sana şu durumda yardımcı olur
  • liste sayfası kayıt sayısı arttıkça yavaşlıyor
  • loglarda aynı sorgu yüzlerce kez tekrar ediyor
  • transaction içinde dış API çağrısı yapılıyor
  • ORM migration indeks oluşturmadan canlıya çıktı
  • eager loading büyük veri patlaması yaratıyor
Yazıyı bitirince

ORM kaynaklı performans sorunlarını veritabanı hatası sanmadan ayırabilecek, N+1 ve transaction problemlerini daha erken yakalayabilecek ve indeksleri kullanım desenine göre düşünebileceksiniz.

TürkDB açısından ürünleşme notu

Bu bölüm, TürkDB’nin ilgili problemi hangi ürün ilkeleri ve kontrol noktalarıyla ele alacağını anlatır. Kapsam, gerçek iş yükü ve ihtiyaçla birlikte netleşir.

TürkDB yavaş sorgu, bağlantı ve kapasite sinyallerini görünür kılmayı hedefler. Ancak ORM’in hangi sorguyu ürettiğini uygulama ekibi görmelidir; platform, semptomu ortaya koyar, kök neden çoğu zaman kodun sorgu desenindedir.

ORM veritabanını gizlediğinde sorun başlar

ORM kullanmak üretkenliği artırır. Model sınıflarıyla çalışmak, migration üretmek ve ilişkileri koddan okumak geliştiriciyi hızlandırır. Sorun, ORM’in ürettiği SQL hiç görülmediğinde başlar.

Bir liste sayfası 50 kayıt getirirken her kayıt için ayrıca kullanıcı, ürün veya yorum sorgusu atıyorsa N+1 oluşur. Küçük veride fark edilmez; canlı ortamda kayıt sayısı büyüyünce veritabanı gereksiz sorgu altında ezilir.

  • Geliştirme ortamında SQL logu belli senaryolarda açılmalıdır.
  • Liste sayfaları sorgu sayısı ve toplam süreyle test edilmelidir.
  • Lazy loading ve eager loading kararları bilinçli verilmelidir.
  • ORM migration çıktısı indeks açısından gözden geçirilmelidir.

N+1 sorguyu sayarak yakalayın

N+1 sorunu çoğu zaman gözle değil logla anlaşılır. Aynı SELECT kalıbının küçük parametre farklarıyla tekrar tekrar çalıştığını görürsünüz. Çözüm bazen join, bazen batch loading, bazen de ayrı bir okuma modeli kurmaktır.

Ama her şeyi eager load etmek de çözüm değildir. Gereksiz eager loading, tek sorguda devasa veri döndürüp belleği ve ağı yorabilir.

N+1 kontrol notu

orm-n1-checklist.md
Sayfa / endpoint:
Dönen kayıt sayısı:
Toplam SQL sorgusu:
Tekrarlayan sorgu kalıbı:
Toplam veritabanı süresi:
Çözüm adayı: join / batch load / read model / cache
İndeks ihtiyacı:

Transaction içinde beklemeyin

ORM ile transaction açmak kolaydır; bu yüzden bazen fazla geniş kullanılır. Transaction içinde e-posta göndermek, dış API çağırmak, dosya işlemek veya kullanıcı cevabını beklemek kilitleri gereksiz yere uzun tutabilir.

İyi transaction kısa, net ve veritabanı işiyle sınırlıdır. Dış sistem çağrıları için outbox veya işlem sonrası asenkron akış daha sağlıklı olabilir.

Migration çıktılarını indeks gözüyle okuyun

ORM migration tabloyu ve foreign key’i oluşturabilir ama sorgularınızın ihtiyaç duyduğu composite indexleri otomatik bilmez. Özellikle tenant_id, status, created_at gibi birlikte filtrelenen kolonlar için indeks tasarımı kullanım desenine göre yapılmalıdır.

Canlıya çıkmadan önce en kritik listeleme, arama ve rapor sorgularının EXPLAIN çıktısı alınmalıdır. ORM kullanmak bu sorumluluğu ortadan kaldırmaz.

Sık listeleme için indeks fikri

orm-index-example.sql
create index concurrently idx_orders_tenant_status_created
on orders (tenant_id, status, created_at desc);

PostgreSQL örneğidir. MySQL ve diğer motorlarda indeks oluşturma davranışı ayrıca değerlendirilmelidir.

Devam etmek istersen

Sorunu motor bazında derinleştirin

Benzer belirtiler farklı motorlarda farklı nedenlere dayanır; yayınlanan tüm rehberleri ana sayfadan takip edebilirsiniz.

Tüm makaleler