Performans ve önbellek
Sayfalama, projeksiyon ve yanıt boyutu
Bütün tabloyu göndermemek: sınır koymak, yalnız gerekeni seçmek ve sıkıştırmak.
Kavramı anlayalım
Bir liste uç noktası ‘hepsini’ döndürüyorsa, veri büyüdükçe yavaşlar ve bir gün çöker. Sayfalama, her istekte sınırlı sayıda kayıt döndürür. En basit biçim offset/limit’tir (Skip/Take); anlaşılırdır ve sayfa numarasıyla doğrudan erişime izin verir. Çok derin sayfalarda veritabanı atlanan satırları da okumak zorunda kaldığı için yavaşlar; bu durumda ‘keyset’ (son görülen değerden sonrası) sayfalama tercih edilir.
Sınır sunucu tarafında zorunlu olmalıdır: istemci ‘limit=100000’ gönderebilir. Bu projede blog API’si sayfa başına en fazla 40 kayıt kabul eder ve arayüz sayfa başına 5 kayıt ister. Sıralama da her zaman belirli olmalıdır; sırasız sayfalama aynı kaydı iki sayfada gösterebilir veya bazılarını hiç göstermeyebilir.
Yanıt boyutunu küçültmenin diğer yolları: projeksiyonla yalnız gereken alanları döndürmek, liste ile ayrıntı için farklı DTO’lar kullanmak ve yanıtları sıkıştırmak (Brotli/gzip). Liste sayfasında yazının tam içeriğini göndermek, kullanıcının hiç görmeyeceği yüzlerce kilobaytı ağdan geçirmek demektir.
Sınırsız uç noktalar hem performans hem de hizmet dışı bırakma (DoS) riski taşır.
İstemcinin gönderdiği limit değerine üst sınır koymamak veya sıralama olmadan sayfalamak.
Aynı konu. Üç farklı derinlik.
var pageSize = Math.Clamp(limit, 1, 40); // sunucu tarafı üst sınır
var items = await db.Posts.AsNoTracking()
.OrderByDescending(p => p.PublishedAtUtc).ThenBy(p => p.Id) // belirli sıra
.Skip(offset).Take(pageSize)
.Select(p => new PostSummary(p.Slug, p.Title, p.Excerpt))
.ToListAsync(ct);Üst sınır, belirli sıralama ve projeksiyon birlikte.
Bu sayfa gerçek bir sunucuya veya veritabanına bağlanmaz. Kod örnekleri .NET 8, Next.js ve SQL Server için temsilîdir; süreler simülasyondaki örnek değerlerdir, ölçüm değildir. Örnekleri yalnız kendi geliştirme ortamında dene; gerçek bağlantı dizesi, token veya parola paylaşma.
Önce kendin dene.
/api/posts?page=500 isteği 4 saniye sürüyor, page=1 ise 20 ms. Neden ve ne önerirsin?
Çözümü ve açıklamasını göster
OFFSET büyüdükçe veritabanı atlanan bütün satırları okur (500 × sayfa boyutu).
Öneri: keyset sayfalama (son görülen tarih+id’den sonrası)
veya derin sayfalara erişimi sınırlamak; uygun indeks (PublishedAtUtc, Id).Offset sayfalamanın maliyeti sayfa numarasıyla doğrusal artar; keyset sabit kalır.