API Pagination Desenleri: Offset, Cursor ve Keyset Pagination
Bir API'nin milyonlarca kaydı tek bir yanıtta döndürmesi ne performans ne de kullanıcı deneyimi açısından mümkündür. Pagination (sayfalama), veriyi küçük, yönetilebilir parçalara bölerek bu sorunu çözer. Ancak doğru deseni seçmek, API'nin ölçeklenebilirliğini ve tutarlılığını doğrudan etkiler. Bu yazıda, üç temel pagination desenini karşılaştıracağız.
1. Offset Pagination: Basit ve Tanıdık
En yaygın kullanılan desendir. İstemci, page (sayfa numarası) ve limit (sayfa boyutu) parametreleri gönderir; sunucu OFFSET ve LIMIT (veya SKIP/TAKE) kullanarak ilgili dilimi döner.
http
GET /api/products?page=3&limit=20
sql
SELECT * FROM Products ORDER BY Id OFFSET 40 ROWS FETCH NEXT 20 ROWS ONLY;
Avantajları:
-
Basitlik: Anlaşılması ve uygulanması kolaydır.
-
Rastgele Erişim: İstemci, doğrudan istediği sayfaya atlayabilir (ör. 5. sayfa).
-
UI Uyumu: Sayfa numaraları (1, 2, 3...) ile gezinme gerektiren arayüzler için idealdir.
Dezavantajları:
-
Performans: Büyük
OFFSETdeğerleri, veritabanının önceki tüm satırları taramasına neden olur.OFFSET 1000000gibi bir sorgu, milyonlarca satırı okuyabilir. -
Tutarsızlık: Sayfalar arasında veri eklenir/silinirse, aynı sayfa numarası farklı veriler döndürebilir veya bazı kayıtlar atlanabilir.
Ne Zaman Kullanılır?
-
Küçük-orta ölçekli veri kümeleri (<10.000 kayıt).
-
Sayfa numaralarıyla gezinme gerektiren UI'lar.
-
Veri setinin sık değişmediği durumlar.
2. Cursor Pagination: İmleçle İlerle
Cursor pagination, her yanıtta bir imleç (cursor) döner; istemci bir sonraki sayfayı almak için bu imleci kullanır. Cursor genellikle son kaydın benzersiz kimliği (ör. Id veya CreatedAt) kodlanmış halidir.
http
GET /api/products?cursor=eyJpZCI6MTIzfQ==&limit=20
sql
SELECT * FROM Products WHERE Id > 123 ORDER BY Id LIMIT 20;
Avantajları:
-
Yüksek Performans:
OFFSETkullanmadığı için index üzerinde doğrudan arama yapar (index seek). Büyük veri kümelerinde bile performans sabit kalır. -
Tutarlılık: Sayfalar arasında veri değişse bile, cursor belirli bir referans noktasından sonrasını getirdiği için atlama veya tekrar olmaz.
-
Sonsuz Kaydırma: Infinite scroll deneyimi için idealdir.
Dezavantajları:
-
Rastgele Erişim Yok: İstemci doğrudan 5. sayfaya atlayamaz; sırayla ilerlemek zorundadır.
-
Karmaşıklık: Cursor'ın kodlanması, çözülmesi ve istemci tarafında yönetilmesi gerekir.
-
Sıralama Kısıtı: Sıralama genellikle cursor sütununa göre yapılır; farklı sıralamalar için farklı cursor'lar gerekir.
Ne Zaman Kullanılır?
-
Çok büyük veri kümeleri (milyonlarca kayıt).
-
Infinite scroll veya "daha fazla yükle" deneyimi.
-
Gerçek zamanlı veya sık değişen veri setleri.
3. Keyset Pagination: Çoklu Sütun Esnekliği
Keyset pagination, cursor pagination'ın gelişmiş bir versiyonudur. İmleç yerine, son kaydın sıralama anahtarlarını (keys) kullanır. Bu sayede birden fazla sütuna göre sıralama yapılabilir.
http
GET /api/products?lastName=Smith&lastId=123&limit=20
sql
SELECT * FROM Products WHERE (Name > 'Smith') OR (Name = 'Smith' AND Id > 123) ORDER BY Name, Id LIMIT 20;
Avantajları:
-
Cursor'ın Tüm Avantajları: Yüksek performans ve tutarlılık.
-
Çoklu Sütun Sıralama:
ORDER BY Name, Idgibi karmaşık sıralamalar desteklenir.
Dezavantajları:
-
Karmaşıklık: Hem sunucu hem istemci tarafında daha fazla mantık gerektirir.
-
NULL Değerler: NULL içeren sütunlarda sıralama ve karşılaştırma zorlaşır.
-
Rastgele Erişim Yok: Cursor gibi, doğrudan sayfa atlaması mümkün değildir.
Ne Zaman Kullanılır?
-
Cursor'ın avantajlarına ek olarak çoklu sütun sıralama gerektiğinde.
-
Örneğin, önce kategoriye, sonra fiyata göre sıralama.
4. Karşılaştırma Tablosu
| Kriter | Offset | Cursor | Keyset |
|---|---|---|---|
| Performans (Büyük Veri) | 🔴 Zayıf | 🟢 Güçlü | 🟢 Güçlü |
| Rastgele Sayfa Atlama | ✅ Evet | ❌ Hayır | ❌ Hayır |
| Tutarlılık | 🔴 Zayıf | 🟢 Güçlü | 🟢 Güçlü |
| Çoklu Sütun Sıralama | ✅ Evet | ❌ Tek sütun | ✅ Evet |
| Uygulama Karmaşıklığı | 🟢 Düşük | 🟡 Orta | 🔴 Yüksek |
| UI Uyumu | Sayfa numaraları | Infinite scroll | Infinite scroll |
5. Pratik Uygulama: Hibrit Yaklaşım
Çoğu üretim API'si, iki deseni birlikte sunar:
-
Offset: Küçük veri kümeleri ve sayfa numaralı gezinme için.
-
Cursor: Büyük veri kümeleri ve sonsuz kaydırma için.
Örneğin, bir e-ticaret API'si, ürün listeleme sayfasında cursor kullanırken, yönetim panelinde offset kullanabilir.
6. En İyi Pratikler
| Pratik | Açıklama |
|---|---|
| Büyük veri için cursor/keyset kullanın | Offset, milyonlarca kayıtta performansı düşürür. |
| Cursor'ı opak tutun | Base64 ile kodlayın; istemci içeriğini bilmesin. |
| Sıralama sütununa index ekleyin | Cursor ve keyset pagination, index olmadan yavaşlar. |
| Toplam sayıyı opsiyonel yapın | COUNT(*) pahalıdır; cursor pagination'da genellikle gerekmez. |
next_cursor ve has_more döndürün |
İstemcinin bir sonraki sayfayı kolayca almasını sağlayın. |
Sonuç
Pagination, API tasarımının görünmez ama kritik bir parçasıdır. Offset pagination, basitliği ve rastgele erişimi ile küçük veri kümeleri için uygundur. Cursor pagination, büyük veri kümelerinde yüksek performans ve tutarlılık sunar. Keyset pagination ise çoklu sütun sıralama ihtiyacı olan senaryolarda esneklik sağlar. Doğru desen, veri boyutuna ve kullanıcı deneyimi gereksinimlerine göre seçilmelidir. Unutmayın: İyi bir pagination, kullanıcının veriyi keşfetmesini sağlarken sunucunun dizlerinin üzerine çökmemesini garanti eder.