TL;DR
Büyük veri kümeleri için, ofset tabanlı sayfalama yerine imleç tabanlı veya anahtar kümesi sayfalama kullanın. Ofset sayfalama (?page=1&limit=20), milyonlarca kayıtla kötü performans gösterir ve veri tutarsızlığına yol açar. Modern PetstoreAPI, verimli ve tutarlı sonuçlar için opak belirteçler ve HATEOAS bağlantılarıyla imleç tabanlı sayfalama uygular.
Giriş
API'niz bir evcil hayvan listesi döndürüyor. Veritabanınızda 10 milyon evcil hayvan var. Bir istemci GET /pets?page=500000&limit=20 isteğinde bulunuyor. Veritabanınız OFFSET 10000000 LIMIT 20 komutunu çalıştırıyor. Sorgu 30 saniye sürüyor. API'niz zaman aşımına uğruyor.
Bu, ofset sayfalama sorunudur. Küçük veri kümeleri için iyi çalışır ancak ölçek büyüdüğünde bozulur. Veritabanı, yalnızca 20 sonuç döndürseniz bile, ofsete ulaşmak için milyonlarca satırı taramak zorundadır.
Eski Swagger Petstore, sayfalama konusuna hiç değinmez. Modern PetstoreAPI, milyonlarca kayda tutarlı performansla ölçeklenebilen imleç tabanlı sayfalama uygular.
Bu kılavuzda, ofset sayfalama neden başarısız olduğunu, imleç tabanlı sayfalama nasıl çalıştığını ve Modern PetstoreAPI'nin verimli sayfalama nasıl uyguladığını öğreneceksiniz.
Ofset Sayfalama Neden Ölçekte Başarısız Olur
Ofset sayfalama en yaygın yaklaşımdır, ancak ciddi sorunları vardır.
Ofset Sayfalama Nasıl Çalışır
GET /pets?page=1&limit=20 → OFFSET 0 LIMIT 20
GET /pets?page=2&limit=20 → OFFSET 20 LIMIT 20
GET /pets?page=3&limit=20 → OFFSET 40 LIMIT 20
Veritabanı offset kadar satırı atlar ve limit kadar satır döndürür.
Sorun 1: Sayfa Numarasıyla Performans Düşer
Sayfa 1:
SELECT * FROM pets OFFSET 0 LIMIT 20;
-- Hızlı: 20 satırı tarar
Sayfa 1000:
SELECT * FROM pets OFFSET 20000 LIMIT 20;
-- Yavaş: 20.020 satırı tarar, 20 tanesini döndürür
Sayfa 500.000:
SELECT * FROM pets OFFSET 10000000 LIMIT 20;
-- Çok yavaş: 10.000.020 satırı tarar, 20 tanesini döndürür
Veritabanı, bu satırları atsa bile, ofsete kadar tüm satırları taramak zorundadır. Performans, sayfa numarasıyla doğrusal olarak düşer.
Sorun 2: Tutarsız Sonuçlar
Bir istemci sonuçlar arasında sayfalamaya devam ederken, veriler değişir:
İstek 1:
GET /pets?page=1&limit=2
Returns: [Pet A, Pet B]
Birisi Evcil Hayvan Z'yi ekler (alfabetik olarak ilk sıraya gelir)
İstek 2:
GET /pets?page=2&limit=2
Returns: [Pet B, Pet C] ← Evcil Hayvan B iki kez görünüyor!
Yeni bir evcil hayvan eklendiği için Evcil Hayvan B her iki sayfada da göründü. Tersine, silme işlemleri meydana gelirse evcil hayvanlar atlanabilir.
Sorun 3: Derin Sayfalama Maliyetlidir
Kullanıcılar nadiren 10. sayfayı geçer. Ancak API'niz ?page=1000000'e izin veriyorsa, bunu yönetmeniz gerekir. Derin sayfalama sorguları pahalıdır ve hizmet reddi saldırıları için kullanılabilir.
Ofset Sayfalama Ne Zaman Kabul Edilebilir
Ofset sayfalama şunlar için iyi çalışır:
- Küçük veri kümeleri (< 10.000 kayıt)
- Kontrollü kullanıma sahip dahili API'ler
- Kullanıcıların derin sayfalama yapmayacağı yönetici arayüzleri
- Seyrek değişen veriler
Herkese açık API'ler veya büyük veri kümeleri için imleç tabanlı sayfalama kullanın.
İmleç Tabanlı Sayfalama Açıklaması
İmleç tabanlı sayfalama, sonuç kümesindeki konumu işaretlemek için opak bir belirteç kullanır.
Nasıl Çalışır
İstek 1:
GET /pets?limit=20
Yanıt 1:
{
"data": [...],
"pagination": {
"nextCursor": "eyJpZCI6IjAxOWI0MTMyLTcwYWEtNzY0Zi1iMzE1LWUyODAzZDg4MmEyNCJ9",
"hasMore": true
}
}
İstek 2:
GET /pets?cursor=eyJpZCI6IjAxOWI0MTMyLTcwYWEtNzY0Zi1iMzE1LWUyODAzZDg4MmEyNCJ9&limit=20
İmleç, konumu kodlayan (genellikle base64 kodlu) opak bir belirteçtir. İstemci onu ayrıştırmaz—sadece geri gönderir.
Faydaları
1. Tutarlı Performans
Veritabanı, imleç konumunu doğrudan bulmak için bir indeks kullanır:
SELECT * FROM pets
WHERE id > '019b4132-70aa-764f-b315-e2803d882a24'
ORDER BY id
LIMIT 20;
Bu sorgu, veri kümesindeki konumdan bağımsız olarak hızlıdır. Bir indeks taraması değil, indeks araması kullanır.
2. Tutarlı Sonuçlar
İmleçler kararlıdır. İstekler arasında veri değişse bile tutarlı sonuçlar alırsınız. Yeni kayıtlar tekrarlara veya atlamalara neden olmaz.
3. Derin Sayfalama Saldırıları Yok
İstemciler rastgele konumlara atlayamazlar. Sıralı olarak sayfalamalıdırlar, bu da kötüye kullanımı sınırlar.
İmleç Formatı
İmleçler tipik olarak base64 kodlu JSON formatındadır:
// Çözülmüş imleç
{
"id": "019b4132-70aa-764f-b315-e2803d882a24",
"createdAt": "2026-03-13T10:30:00Z"
}
İmleç, sayfalamayı sürdürmek için yeterli bilgiyi içerir. Modern PetstoreAPI için bu, kaynak kimliğini ve sıralama alanını içerir.
Sıralı Veriler İçin Anahtar Kümesi Sayfalama
Anahtar kümesi sayfalama, sıralı veriler için imleç tabanlı sayfalama varyantıdır.
Nasıl Çalışır
Opak bir imleç yerine, önceki sayfadan son değeri kullanırsınız:
İstek 1:
GET /pets?limit=20&sortBy=createdAt
Yanıt 1:
{
"data": [
{"id": "...", "createdAt": "2026-03-13T10:00:00Z"},
...
{"id": "...", "createdAt": "2026-03-13T10:30:00Z"}
]
}
İstek 2:
GET /pets?limit=20&sortBy=createdAt&after=2026-03-13T10:30:00Z
after parametresi, önceki sayfadan alınan son createdAt değerini kullanır.
SQL Sorgusu
SELECT * FROM pets
WHERE created_at > '2026-03-13T10:30:00Z'
ORDER BY created_at
LIMIT 20;
Bu, `created_at` üzerinde bir indeks kullandığı için verimlidir.
Anahtar Kümesi Sayfalama Ne Zaman Kullanılır
- Veriler doğal olarak sıralanmıştır (zaman damgası, Kimlik vb. ile)
- İstemcilerin sayfalama anahtarını anlaması gerekir
- Şeffaf sayfalama istiyorsunuz (opak imleçler değil)
Modern PetstoreAPI varsayılan olarak imleç tabanlı sayfalama kullanır ancak zaman serisi verileri için anahtar kümesi sayfalama desteği sunar.
Modern PetstoreAPI Sayfalama Nasıl Uygular
Modern PetstoreAPI, HATEOAS bağlantılarıyla imleç tabanlı sayfalama kullanır.
İstek Formatı
GET /pets?limit=20
GET /pets?cursor={token}&limit=20
Parametreler:
limit- Sayfa başına sonuç sayısı (varsayılan: 20, maks: 100)cursor- Önceki yanıttan alınan opak sayfalama belirteci
Yanıt Formatı
{
"data": [
{
"id": "019b4132-70aa-764f-b315-e2803d882a24",
"name": "Fluffy",
"species": "CAT"
}
],
"pagination": {
"limit": 20,
"hasMore": true,
"nextCursor": "eyJpZCI6IjAxOWI0MTMyLTcwYWEtNzY0Zi1iMzE1LWUyODAzZDg4MmEyNCJ9"
},
"links": {
"self": "https://petstoreapi.com/pets?limit=20",
"next": "https://petstoreapi.com/pets?cursor=eyJpZCI6IjAxOWI0MTMyLTcwYWEtNzY0Zi1iMzE1LWUyODAzZDg4MmEyNCJ9&limit=20"
}
}
Temel Özellikler
1. Opak İmleçler
İmleçler base64 kodludur. İstemciler bunları ayrıştırmaz.
2. HATEOAS Bağlantıları
links nesnesi kullanıma hazır URL'ler sağlar. İstemcilerin sayfalama URL'lerini oluşturmasına gerek yoktur.
3. hasMore Bayrağı
Daha fazla sonuç olup olmadığını gösterir. İstemciler ne zaman sayfalamayı durduracaklarını bilirler.
4. Limit Doğrulama
Maksimum limit 100'dür. İstemcilerin çok büyük sayfalar talep etmesini engeller.
Tüm ayrıntılar için Modern PetstoreAPI sayfalama dokümantasyonuna bakın.
Sayfalama Yanıt Formatı
Modern PetstoreAPI, sayfalanmış yanıtları tutarlı bir yapıda sarmalar.
Koleksiyon Sarmalayıcı
{
"data": [...],
"pagination": {...},
"links": {...}
}
Koleksiyonlar neden sarmalanır?
- Genişletilebilirlik - İstemcileri bozmadan meta veri eklenebilir
- Tutarlılık - Tüm sayfalanmış uç noktalar aynı formatı kullanır
- HATEOAS - Bağlantılar istemcilere sayfalama boyunca rehberlik eder
Sayfalama Meta Verileri
"pagination": {
"limit": 20,
"hasMore": true,
"nextCursor": "...",
"totalCount": 1000 // İsteğe bağlı, hesaplaması maliyetli
}
totalCount isteğe bağlıdır çünkü büyük veri kümeleri için hesaplanması maliyetlidir. Çoğu istemcinin buna ihtiyacı yoktur.
Apidog ile Sayfalama Testi
Apidog, sayfalama davranışını kapsamlı bir şekilde test etmenize yardımcı olur.
Test Senaryoları
1. İlk Sayfa
GET /pets?limit=20
Beklenti: 20 sonuç, hasMore=true, nextCursor mevcut
2. Sonraki Sayfalar
GET /pets?cursor={token}&limit=20
Beklenti: 20 sonuç, hasMore=true/false, nextCursor mevcut/yok
3. Son Sayfa
GET /pets?cursor={lastToken}&limit=20
Beklenti: < 20 sonuç, hasMore=false, nextCursor yok
4. Boş Sonuçlar
GET /pets?status=NONEXISTENT&limit=20
Beklenti: 0 sonuç, hasMore=false, nextCursor yok
5. Limit Doğrulama
GET /pets?limit=1000
Beklenti: 400 Hatalı İstek (maksimum limiti aşıyor)
Apidog Test Yapılandırması
// Test: Sayfalama yapısı
pm.test("Response has pagination", () => {
pm.expect(pm.response.json()).to.have.property('pagination');
pm.expect(pm.response.json().pagination).to.have.property('hasMore');
});
// Test: HATEOAS bağlantıları
pm.test("Response has links", () => {
const links = pm.response.json().links;
pm.expect(links).to.have.property('self');
if (pm.response.json().pagination.hasMore) {
pm.expect(links).to.have.property('next');
}
});
Doğru Sayfalama Stratejisini Seçmek
Farklı stratejiler farklı kullanım durumlarına uyar.
Ofset Sayfalama
Şu durumlarda kullanın:
- Veri kümesi küçükse (< 10.000 kayıt)
- Kullanıcılar rastgele erişime ihtiyaç duyuyorsa (sayfa 50'ye atlama)
- Veriler seyrek değişiyorsa
- Kontrollü kullanıma sahip dahili API'ler için
Şu durumlarda kullanmayın:
- Veri kümesi büyükse (> 100.000 kayıt)
- Performans önemliyse
- Veriler sık değişiyorsa
İmleç Tabanlı Sayfalama
Şu durumlarda kullanın:
- Veri kümesi büyükse
- Performans önemliyse
- Veriler sık değişiyorsa
- Sıralı erişim yeterliyse
Şu durumlarda kullanmayın:
- Kullanıcılar rastgele erişime ihtiyaç duyuyorsa
- İmleç karmaşıklığı bir endişe kaynağıysa
Anahtar Kümesi Sayfalama
Şu durumlarda kullanın:
- Veriler doğal olarak sıralanmışsa
- Şeffaf sayfalama tercih ediliyorsa
- Performans önemliyse
Şu durumlarda kullanmayın:
- Sıralama düzeni karmaşıksa
- Birden fazla sıralama alanına ihtiyaç varsa
Modern PetstoreAPI önerisi: Herkese açık API'ler ve büyük veri kümeleri için imleç tabanlı sayfalama kullanın.
Sonuç
Sayfalama, büyük veri kümeleri döndüren API'ler için kritik öneme sahiptir. Ofset sayfalama basittir ancak ölçeklenmez. İmleç tabanlı sayfalama, milyonlarca kayıt için tutarlı performans ve güvenilir sonuçlar sağlar.
Modern PetstoreAPI, opak belirteçler, HATEOAS bağlantıları ve uygun meta verilerle imleç tabanlı sayfalama uygular. Bu tasarım verimli bir şekilde ölçeklenir ve harika bir geliştirici deneyimi sunar.
Uç durumları ele aldığından, limitleri doğruladığından ve tutarlı sonuçlar döndürdüğünden emin olmak için sayfalama uygulamanızı Apidog ile test edin.
Önemli çıkarımlar:
- Büyük veri kümeleri için ofset sayfalamadan kaçının
- Ölçeklenebilirlik için imleç tabanlı sayfalama kullanın
- Koleksiyonları meta veriler ve bağlantılarla sarmalayın
- Apidog ile sayfalamayı kapsamlı bir şekilde test edin
- Modern PetstoreAPI’nin sayfalama desenlerini takip edin
Sıkça Sorulan Sorular
Neden tüm sonuçları sayfalama yapmadan döndürmeyelim?
Milyonlarca kaydı tek bir yanıtta döndürmek bellek sorunlarına, yavaş ağ transferine ve kötü kullanıcı deneyimine neden olur. Sayfalama, büyük veri kümeleri için hayati öneme sahiptir.
İstemciler imleçli sayfalama ile belirli bir sayfaya atlayabilir mi?
Hayır, imleçli sayfalama sıralı erişim gerektirir. Rastgele erişim gerekiyorsa, küçük veri kümeleri için ofset sayfalamayı düşünün veya bunun yerine arama/filtreleme uygulayın.
Filtreleme ile sayfalamayı nasıl yaparım?
Sayfalama isteklerine filtre parametrelerini ekleyin: GET /pets?status=AVAILABLE&cursor={token}&limit=20. İmleç hem konumu hem de filtre durumunu kodlar.
Sayfalama yanıtlarına toplam sayıyı eklemeli miyim?
Yalnızca istemciler buna ihtiyaç duyuyorsa ve veri kümeniz küçükse ekleyin. Toplam sayıyı hesaplamak, büyük veri kümeleri için pahalıdır (ayrı bir COUNT sorgusu gerektirir).
SQL'de imleçli sayfalamayı nasıl uygularım?
İmleç değeriyle bir WHERE yan tümcesi kullanın: SELECT * FROM pets WHERE id > ? ORDER BY id LIMIT 20. Sıralama sütununda bir indeksiniz olduğundan emin olun.
İmleç belirteçlerim geçersiz olursa ne olur?
Bir hata mesajıyla 400 Hatalı İstek döndürün. Veriler silinirse veya sayfalama durumu sona ererse imleçler geçersiz hale gelebilir.
İmleçler ne kadar süreyle geçerli kalmalıdır?
Modern PetstoreAPI imleçleri, referans verilen kaynak var olduğu sürece süresiz olarak geçerlidir. Bazı API'ler imleçleri 24 saat sonra sona erdirir.
Birden fazla sıralama alanı ile imleçli sayfalama kullanabilir miyim?
Evet, ancak imleç tüm sıralama alanlarını kodlamalıdır. Bu, imleçleri daha karmaşık hale getirir. Bunun yerine tek bir bileşik sıralama anahtarı kullanmayı düşünün.
