DEV Community

Mustafa  Çam
Mustafa Çam

Posted on

Çok fazla ilişkili verilerle çalışmak.

"Çok fazla ilişkili veri ile çalışmak" ifadesi, bir nesneyle ilişkili olan çok sayıda alt nesneye erişmeyi veya bu nesneleri sorgulamayı ifade eder. Özellikle veritabanı modellerinde birden fazla ilişki (birden çoğa, çoktan çoğa gibi) olduğunda, bu ilişkili verilerin aşırı miktarda olması durumunda performans sorunları yaşanabilir.

Örnek Durum: "Çok Fazla İlişkili Veri" Nedir?

Bir senaryo düşünelim:

  • Bir Student (öğrenci) tablonuz var.
  • Her öğrenci birçok Course (ders) ile ilişkilendirilmiş.
  • Ayrıca her dersin birçok Instructor (öğretmen) ve birçok Assignment (ödev) ile ilişkisi var.

Bu durumda, bir öğrenciyi sorguladığınızda, öğrenci ile ilişkili kurslar, her kurs ile ilişkili öğretmenler, ve her kursa ait ödevler gibi çok sayıda veri gelebilir. Bu ilişkiler derinleştikçe, veritabanından çekilen veri miktarı da önemli ölçüde artabilir.

Tembel Yükleme (Lazy Loading) ve İlişkili Veriler

Tembel yüklemede, her ilişkili veri sorgulandığında veritabanına bir istek gönderilir. Eğer çok fazla ilişkili veri varsa ve her birine ayrı ayrı erişirseniz, veritabanına çok sayıda küçük sorgu gönderilir. Bu da n+1 sorgu problemi olarak bilinen durumu doğurabilir:

  • Örnek: Bir öğrenci ve onun kursları için, öğrenciyi aldığınızda veritabanına 1 sorgu gider, ama kurslarına eriştiğinizde her kurs için ayrı bir sorgu gider.
var student = context.Students.Find(1); // 1 sorgu
foreach (var course in student.Courses) // Her course için ayrı sorgular (n sorgu)
{
    Console.WriteLine(course.Title);
}
Enter fullscreen mode Exit fullscreen mode

Burada, n+1 sorgu problemi doğar, çünkü 1 ana sorguya ek olarak n tane ilişkili sorgu veritabanına gönderilir. Bu ilişkiler çok karmaşıksa (örneğin her kursun ödevleri de getirilirse), her bir ilişki için yeni sorgular eklenir ve bu da veritabanı performansını ciddi şekilde etkileyebilir.

"Çok Fazla İlişkili Veri" Ne Zaman Sorun Yaratır?

  • Büyük Veri Kümeleri: Eğer bir öğrenci yüzlerce kursa, her kurs da yüzlerce ödeve sahipse, bu durumda yüzlerce, hatta binlerce veri veritabanından çekilecektir. Bu, bellekte büyük yer kaplayacak ve uygulamanın yavaşlamasına neden olabilir.

  • Derin İlişkiler: Bir veri yapısının çok fazla seviyede ilişkili tablosu varsa (örneğin öğrenci > kurs > öğretmen > ders notları gibi), her bir seviye için ek sorgular çalıştırılabilir, bu da veritabanına aşırı yük bindirir.

  • N+1 Sorgu Problemi: Yukarıda bahsettiğimiz gibi, ilişkili verilerde tembel yükleme kullanıldığında, veritabanına gereksiz yere birçok küçük sorgu gönderilmesi n+1 sorgu problemine yol açar. Bu da çok fazla ilişki olduğunda uygulamanın performansını ciddi şekilde düşürebilir.

Performansı İyileştirme Stratejileri

Eğer çok fazla ilişkili veriyle çalışıyorsanız, performansı iyileştirmek için birkaç strateji kullanabilirsiniz:

  1. Eager Loading (Açık Yükleme): İlişkili verileri baştan, tek bir sorgu ile yüklemek. Böylece n+1 problemi ortadan kalkar. Örneğin, Include kullanarak ilişkili verileri tek bir sorguyla alabilirsiniz:
   var students = context.Students
                         .Include(s => s.Courses)
                         .ThenInclude(c => c.Instructors)
                         .ToList();
Enter fullscreen mode Exit fullscreen mode
  1. Explicit Loading (Açıkça Yükleme): İhtiyaç duyduğunuz verileri gerektiğinde açıkça yüklemek. Örneğin, bir öğrenci getirildiğinde kursları otomatik olarak yüklenmez, ancak kurslara erişmek istediğinizde elle yüklenir:
   var student = context.Students.Find(1);
   context.Entry(student).Collection(s => s.Courses).Load();
Enter fullscreen mode Exit fullscreen mode
  1. Filtreleme (Projection): İlişkili verilerin tamamını değil, sadece gerçekten ihtiyaç duyduğunuz alanları ve verileri sorgulamak. Örneğin:
   var studentCourses = context.Students
                               .Where(s => s.StudentId == 1)
                               .Select(s => new { s.Name, Courses = s.Courses.Select(c => c.Title) })
                               .ToList();
Enter fullscreen mode Exit fullscreen mode
  1. Sayfalama (Paging): Çok büyük veri setlerini getirmek yerine, verileri sayfalar halinde alarak sorguları daha küçük parçalara bölmek. Bu, hafızada daha az yer kaplar ve daha hızlı sonuç döndürür.
   var students = context.Students.Skip(0).Take(20).ToList();
Enter fullscreen mode Exit fullscreen mode

Sonuç

Çok fazla ilişkili veriyle çalışmak, özellikle n+1 sorgu problemi gibi sorunlar ortaya çıkarabileceğinden dikkat edilmesi gereken bir konudur. Eğer veritabanında derin ilişkiler veya büyük veri setleri varsa, ilişkili verilerin nasıl yükleneceğine karar verirken performans optimizasyonlarına dikkat etmeniz gerekir.

Top comments (0)