03 Eki 2025·6 dk okuma

Hızlı yönetici ekranı API'leri için cursor ve offset sayfalama

Sıralama, filtre ve toplamlar için tutarlı bir API sözleşmesiyle cursor ve offset sayfalamayı öğrenin; web ve mobil yönetici ekranlarını hızlı tutun.

Hızlı yönetici ekranı API'leri için cursor ve offset sayfalama

Neden sayfalama yönetici ekranlarını yavaş hissettirebilir

Yönetici ekranları genellikle basit bir tablo olarak başlar: ilk 25 satırı yükle, bir arama kutusu ekle, tamam. Birkaç yüz kayıtla anlık gibi hisseder. Sonra veri büyür ve aynı ekran takılmaya başlar.

Sorun genellikle UI'da değildir. Sorun, API'nin sayfa 12'yi sıralama ve filtrelerle döndürmeden önce yapmak zorunda olduklarıdır. Tablo büyüdükçe backend, eşleşenleri bulmak, onları saymak ve önceki sonuçları atlamak için daha fazla zaman harcar. Her tıklama daha ağır bir sorguyu tetikliyorsa, ekran cevap vermekten çok "düşünüyor" gibi hisseder.

Bunu genelde aynı yerlerde fark edersiniz: sayfa değişiklikleri zamanla yavaşlar, sıralama yavaşlar, arama sayfalar arasında tutarsız hissedilir ve infinite scroll patlamalı yükler (hızlı, sonra aniden yavaş) yapar. Yoğun sistemlerde veriler istekler arasında değiştiğinde tekrarlar veya kayıp satırlar bile görebilirsiniz.

Web ve mobil UI'lar sayfalamayı farklı yönlere iter. Web yönetici tablosu belirli bir sayfaya atlamayı ve birçok sütuna göre sıralamayı teşvik eder. Mobil ekranlar genelde bir sonraki parçayı yükleyen sonsuz bir liste kullanır ve kullanıcılar her çekişin aynı hızlı olmasını bekler. API'niz sadece sayfa numaralarına göre kurulmuşsa, mobil genellikle zarar görür. Sadece next/after etrafında kurulmuşsa, web tabloları sınırlı hissedebilir.

Amaç sadece 25 öğe döndürmek değil. Amaç veri büyüdükçe hızlı, öngörülebilir sayfalamayı koruyan ve tablolar ile infinite listeler için aynı şekilde işleyen kurallar koymaktır.

UI'nizin bağlı olduğu sayfalama temelleri

Sayfalama uzun bir listeyi daha küçük parçalara ayırmaktır, böylece ekran hızlıca yükleyip render edebilir. UI her kaydı istemek yerine sonuçların bir sonraki dilimini ister.

En önemli kontrol sayfa boyutudur (genellikle limit diye anılır). Küçük sayfalar genellikle daha hızlı hissedilir çünkü sunucu daha az iş yapar ve uygulama daha az satır çizer. Ancak sayfalar çok küçükse kullanıcıların daha sık tıklaması veya kaydırması gerekir ve bu sıçramalı (jumpy) bir deneyim yaratabilir. Birçok yönetici tablosu için 25 ila 100 öğe pratik bir aralıktır; mobil genelde alt uçları tercih eder.

Stabil bir sıralama çoğu ekipten daha önemli olur. Eğer sıralama istekler arasında değişebiliyorsa, kullanıcılar sayfalandırırken tekrarlar veya eksik satırlar görür. Stabil sıralama genellikle bir birincil alana (örneğin created_at) ve bir tie-breaker'a (örneğin id) göre sıralamak demektir. Bu, offset veya cursor sayfalamayı kullanıyor olmanıza bakılmaksızın önemlidir.

İstemci açısından, sayfalanmış bir yanıt öğeleri, bir sonraki sayfa ipucunu (sayfa numarası veya cursor token) ve UI'nin gerçekten ihtiyaç duyduğu sayımları içermelidir. Bazı ekranlar "1-50 of 12.340" gibi kesin bir toplam ister. Diğerleri sadece has_more ile yetinir.

Offset sayfalama: nasıl çalışır ve nerede zarar verir

Offset sayfalama klasik sayfa N yaklaşımıdır. İstemci sabit sayıda satır ister ve API'ye önce kaç satır atlaması gerektiğini söyler. Bunu limit ve offset olarak ya da sunucunun bir offset'e dönüştürdüğü page ve pageSize olarak görürsünüz.

Tipik bir istek şöyle görünür:

  • GET /tickets?limit=50\u0026offset=950
  • “İlk 950'yi atlayarak bana 50 ticket ver.”

Bu, sayfa 20'ye atlamak, eski kayıtları taramak veya büyük bir listeyi parçalar halinde dışa aktarmak gibi yaygın yönetici ihtiyaçlarıyla uyumludur. İçeride tartışması da kolaydır: "Sayfa 3'e bak, göreceksin."

Sorun derin sayfalarda ortaya çıkar. Birçok veritabanı atlanan satırların yanından yürümek zorunda kalır, özellikle sıralama sıkı bir indeks tarafından desteklenmiyorsa. 1. sayfa hızlı olabilir, ama 200. sayfa bariz şekilde yavaşlayabilir; bu da kullanıcıların kaydırdığı veya atladığı zaman yönetici ekranlarını yavaş hissettiren tam şeydir.

Diğer problem veri değiştiğinde tutarlılıktır. Diyelim bir destek yöneticisi en yeniye göre sıralanmış ticketların 5. sayfasını açtı. O sırada yeni ticketlar gelir veya eski ticketlar silinir. Ekleme yapanlar öğeleri ileri kaydırabilir (sayfalar arasında tekrarlar). Silmeler ise öğeleri geri kaydırır (kullanıcının gezindiği yolda kayıtlar kaybolur).

Offset sayfalama küçük tablolar, stabil veri setleri veya tek seferlik dışa aktarımlar için hâlâ uygundur. Büyük, aktif tablolarda kenar durumları hızla görünür hale gelir.

Cursor sayfalama: nasıl çalışır ve neden sabit kalır

Cursor sayfalama bir yer imi olarak cursor kullanır. “Bana 7. sayfayı ver” demek yerine, istemci “bu tam öğeden sonra devam et” der. Cursor genellikle son öğenin sıralama değerlerini (örneğin created_at ve id) kodlar, böylece sunucu doğru yerden devam edebilir.

İstek genellikle sadece şunları içerir:

  • limit: kaç öğe döndürüleceği
  • cursor: önceki yanıttan alınan opak token (çoğunlukla after diye adlandırılır)

Yanıt öğeleri ve bu dilimin sonunu gösteren yeni bir cursor döndürür. Pratik fark şudur: cursor'lar veritabanından satırları sayıp atlamasını istemez. Onun yerine bilinen bir konumdan başlamasını ister.

Bu yüzden cursor sayfalama ileri doğru kayan listelerde hızlı kalır. İyi bir indeksle veritabanı “X'ten sonra gelen öğeler”e atlayabilir ve ardından sonraki limit satırı okuyabilir. Offset'lerde sunucu genellikle atlanan daha çok satırı taramak (veya en azından atlamak) zorunda kalır; offset büyüdükçe iş artar.

UI davranışı açısından, cursor sayfalama “İleri”yi doğal kılar: döndürülen cursor'u alıp bir sonraki istekte geri gönderirsiniz. “Geri” isteğe bağlıdır ve daha karmaşıktır. Bazı API'ler bir before cursor destekler; bazıları ters yönde alıp sonuçları çevirir.

Ne zaman cursor, offset veya hibrit seçilmeli

API sözleşmenizi tutarlı yapın
Tek bir yanıt biçimini standartlaştırın ve her liste endpoint'inde yeniden kullanın.
Başlayın

Seçim, insanların listeyi nasıl kullandığıyla başlar.

Cursor sayfalama çoğunlukla ileriye doğru hareket edildiğinde ve hızın en önemli olduğu durumlar için en uygunudur: etkinlik günlükleri, sohbetler, siparişler, ticketlar, denetim izleri ve çoğu mobil infinite scroll. Ayrıca biri gezinirken yeni satırlar eklendiğinde veya silindiğinde daha iyi davranır.

Offset sayfalama sık sık etrafta zıplanıyorsa mantıklıdır: klasik yönetici tabloları sayfa numaralarıyla, sayfaya gitme ve hızlı ileri-geri gezinme ile. Açıklaması basittir, ancak büyük veri kümelerinde yavaşlayabilir ve veriler altta değiştiğinde daha az stabil hale gelebilir.

Pratik bir karar yolu:

  • Ana eylem “ileri, ileri, ileri” ise cursor seçin.
  • “N. sayfaya atla” gerçek bir gereksinimse offset seçin.
  • Toplamları isteğe bağlı tutun. Büyük tablolarda doğru toplamlar pahalı olabilir.

Hibritler yaygındır. Bir yaklaşım hızlılık için cursor tabanlı next/prev kullanmak, küçük filtrelenmiş altküme için isteğe bağlı sayfa-atlama modu (offset) sunmaktır. Başka bir yaklaşım, önbelleğe alınmış bir snapshot'a dayalı sayfa numaralarıyla cursor alımıdır; tablo tanıdık hissedilir, ancak her isteği ağır hale getirmez.

Web ve mobil için işe yarayan tutarlı bir API sözleşmesi

Yönetici UI'ları, her liste endpoint'i aynı şekilde davrandığında daha hızlı hissedilir. UI değişebilir (web tablosu sayfa numaralarıyla, mobil infinite scroll), ama API sözleşmesi sabit kalmalı, böylece her ekran için sayfalama kuralları yeniden öğrenilmez.

Pratik bir sözleşme üç parçadan oluşur: satırlar, sayfalama durumu ve isteğe bağlı toplamlar. Alan adlarını tüm endpoint'lerde aynı tutun (tickets, users, orders), hatta altta yatan sayfalama modu farklı olsa bile.

Hem web hem mobil için iyi işleyen bir yanıt yapısı şöyle olabilir:

{
  "data": [ { "id": "...", "createdAt": "..." } ],
  "page": {
    "mode": "cursor",
    "limit": 50,
    "nextCursor": "...",
    "prevCursor": null,
    "hasNext": true,
    "hasPrev": false
  },
  "totals": {
    "count": 12345,
    "filteredCount": 120
  }
}

Bunu yeniden kullanmayı kolaylaştıran birkaç detay:

  • page.mode istemciye sunucunun ne yaptığını söyler, alan adlarını değiştirmeden.
  • limit her zaman istenen sayfa boyutudur.
  • nextCursor ve prevCursor biri null olsa bile bulunur.
  • totals isteğe bağlıdır. Eğer pahalıysa, istemci istediğinde dönün.

Bir web tablosu kendi sayfa indeksini tutarak “Sayfa 3” gösterebilir ve API'yi tekrar tekrar çağırır. Bir mobil liste sayfa numaralarını yok sayıp sadece bir sonraki parçayı isteyebilir.

Eğer hem web hem mobil yönetici UI'ları AppMaster ile inşa ediyorsanız, böyle bir sabit sözleşme hızla fayda sağlar. Aynı liste davranışı ekranlar arasında yeniden kullanılabilir ve her endpoint için özel sayfalama mantığı yazmanız azalır.

Sayfalamayı stabil tutan sıralama kuralları

Mobil listeleri optimize edin
Aynı backend'ten hızlı ve öngörülebilir sayfalama ile akıcı infinite scroll sağlayın.
Mobil Uygulama Oluştur

Sıralama, sayfalamanın genelde bozulduğu yerdir. Eğer sıra istekler arasında değişebiliyorsa, kullanıcılar tekrarlar, boşluklar veya “kayıp” satırlar görür.

Sıralamayı öneri değil sözleşme haline getirin. İzin verilen sıralama alanlarını ve yönlerini yayınlayın, ve başka bir şey gelirse reddedin. Bu API'nizi öngörülebilir kılar ve istemcilerin geliştirmede zararsız görünen yavaş sıralamalar istemesini engeller.

Stabil bir sıralama benzersiz bir tie-breaker gerektirir. Eğer created_at ile sıralıyorsanız ve iki kayıt aynı zaman damgasına sahipse, en son anahtar olarak id (veya başka benzersiz bir sütun) ekleyin. Bunu yapmazsanız veritabanı eşit değerleri herhangi bir sırada döndürebilir.

Dayanıklı kurallar:

  • Sadece indekslenmiş, iyi tanımlanmış alanlarda sıralamaya izin verin (örneğin created_at, updated_at, status, priority).
  • Son anahtar olarak her zaman benzersiz bir tie-breaker ekleyin (örneğin id ASC).
  • Bir varsayılan sıralama tanımlayın (örneğin created_at DESC, id DESC) ve istemciler arasında tutarlı tutun.
  • Null'ların nasıl sıralandığını belgeleyin (örneğin tarihler ve sayılar için "nulls last").

Sıralama ayrıca cursor üretimini yönlendirir. Bir cursor son öğenin sıralama değerlerini, tie-breaker dahil, sırasıyla kodlamalıdır, böylece bir sonraki sayfa "o tuple'dan sonra" sorgulanabilir. Sıralama değişirse, eski cursor'lar geçersiz olur. Sıralama parametrelerini cursor sözleşmesinin parçası olarak kabul edin.

Filtreler ve toplamlar: sözleşmeyi bozmadan

Filtreler sayfalamadan ayrı hissettirmeli. UI "farklı bir satır kümesini göster" diyor ve sonra "o kümeyi sayfala" diyor. Filtre alanlarını pagination tokenına karıştırırsanız veya filtreleri isteğe bağlı ve doğrulanmamış tutarsanız, boş sayfalar, tekrarlar veya cursor'un aniden farklı bir veri kümesine işaret ettiği gibi hata ayıklaması zor davranışlar görürsünüz.

Basit kural: filtreler düz sorgu parametrelerinde (veya POST için istek gövdesinde) yaşar, ve cursor opaktır ve yalnızca tam olarak o filtre + sıralama kombinasyonu için geçerlidir. Kullanıcı herhangi bir filtreyi (status, date range, assignee) değiştirdiğinde, istemci eski cursor'u atmalı ve baştan başlamalıdır.

Hangi filtrelere izin verildiği konusunda katı olun. Bu performansı korur ve davranışı öngörülebilir kılar:

  • Bilinmeyen filtre alanlarını reddedin (sessizce görmezden gelmeyin).
  • Türleri ve aralıkları doğrulayın (tarihler, enum'lar, ID'ler).
  • Geniş filtreleri sınırlandırın (örneğin bir IN listesinde en fazla 50 ID).
  • Toplamlara filtreleri uygulayın (uyuşmayan sayılar döndürmeyin).

Toplamlar birçok API'nin yavaşladığı yerdir. Kesin sayımlar büyük tablolarda, özellikle birden fazla filtre ile pahalı olabilir. Genelde üç seçeneğiniz vardır: kesin, tahmini veya yok. Kesin küçük veri kümeleri veya kullanıcıların gerçekten “1-25 of 12,431” gibi görmek istediği durumlar için iyidir. Tahmini genelde yönetici ekranları için yeterlidir. Hiçbirini döndürmemek ise UI yalnızca “Daha fazla yükle” demeyi tercih ediyorsa uygundur.

Her isteği yavaşlatmamak için toplamları isteğe bağlı yapın: istemci istediğinde hesaplayın (örneğin includeTotal=true gibi bir bayrakla), filtre seti başına kısa süreli önbelleğe alın veya toplamları yalnızca ilk sayfada döndürün.

Adım adım: endpoint tasarla ve uygula

Daha hızlı liste endpoint'leri oluşturun
Stabil sıralama ve cursor sayfalama ile hızlı bir liste API'si oluşturun, endpoint'leri elle yazmadan.
AppMaster'ı Deneyin

Varsayılanlarla başlayın. Bir liste endpoint'i stabil bir sıralama ve aynı değeri paylaşan satırlar için bir tie-breaker gerektirir. Örneğin: createdAt DESC, id DESC. Tie-breaker (id) yeni kayıtlar eklendiğinde tekrarları ve boşlukları engeller.

Bir istek şekli tanımlayın ve sıkıcı tutun. Tipik parametreler limit, cursor (veya offset), sort ve filters'tır. Her iki modu da destekliyorsanız, bunları karşılıklı dışlayıcı yapın: ya istemci cursor gönderir ya da offset gönderir, ikisi birden değil.

Web ve mobil UI'ların aynı liste mantığını paylaşabilmesi için yanıt sözleşmesini tutarlı tutun:

  • items: sayfa kayıtları
  • nextCursor: bir sonraki sayfayı almak için cursor (veya null)
  • hasMore: UI'nin “Daha fazla yükle” göstermek için kullanacağı boolean
  • total: eşleşen toplam kayıt sayısı (null; eğer sayma pahalıysa yalnızca istenirse)

Uygulama detayları iki yaklaşımda ayrışır.

Offset sorguları genelde ORDER BY ... LIMIT ... OFFSET ... şeklindedir ve büyük tablolarda yavaşlayabilir.

Cursor sorguları ise son öğeye dayalı seek koşulları kullanır: “(createdAt, id) son (createdAt, id)'den küçük olan öğeleri ver”. Bu, veritabanının indeksleri kullanabilmesi sayesinde performansı daha dengeli tutar.

Yayınlamadan önce şu korumaları ekleyin:

  • limit'i kısıtlayın (örneğin max 100) ve bir varsayılan belirleyin.
  • sort'u izin verilenler listesine göre doğrulayın.
  • Filtreleri türüne göre doğrulayın ve bilinmeyen anahtarları reddedin.
  • cursor'u opak yapın (son sıralama değerlerini encode edin) ve bozuk cursor'ları reddedin.
  • total'ın nasıl istendiğine karar verin.

Veri altınızda değişirken test edin. İstekler arasında kayıt oluşturun ve silin, sıralamayı etkileyen alanları güncelleyin ve tekrarlar ya da eksik satırlar görmediğinizi doğrulayın.

Örnek: web ve mobilde hızlı kalan bir ticket listesi

API'yi gerçek bir UI'ya bağlayın
Sayfalama kurallarınızı AppMaster UI oluşturucularıyla çalışan bir web UI'ya dönüştürün.
Web Uygulama Oluştur

Bir destek ekibi en yeni ticketları incelemek için bir yönetici ekranı açar. Yeni ticketlar gelirken ve ajanlar eski kayıtları güncellerken bile listenin anlık hissetmesini isterler.

Web'de UI bir tablodur. Varsayılan sıralama updated_at (yeniden en yeni) yönündedir ve ekip genelde Open veya Pending filtreleri uygular. Aynı endpoint stabil bir sıralama ve bir cursor token ile her iki durumu da destekleyebilir.

GET /tickets?status=open\u0026sort=-updated_at\u0026limit=50\u0026cursor=eyJ1cGRhdGVkX2F0IjoiMjAyNi0wMS0yNVQxMTo0NTo0MloiLCJpZCI6IjE2OTMifQ==

Yanıt UI için öngörülebilirdir:

{
  "items": [{"id": 1693, "subject": "Login issue", "status": "open", "updated_at": "2026-01-25T11:45:42Z"}],
  "page": {"next_cursor": "...", "has_more": true},
  "meta": {"total": 128}
}

Mobilde aynı endpoint infinite scroll'u besler. Uygulama 20 ticket'ı bir kerede yükler, sonra next_cursor gönderip bir sonraki paketi alır. Sayfa numarası mantığı yoktur ve kayıtlar değiştiğinde daha az sürpriz olur.

Anahtar nokta cursor'ın son görülen konumu kodlamasıdır (örneğin updated_at artı tie-breaker olarak id). Bir ticket kaydı ajan kaydırırken güncellenirse, bir sonraki yenilemede üst tarafa kayabilir ama zaten kaydırılmış akışta tekrarlar veya boşluklar oluşturmaz.

Toplamlar kullanışlıdır ama büyük veri kümelerinde pahalıdır. Basit bir kural: meta.total yalnızca kullanıcı filtre uyguladığında (status=open gibi) veya açıkça istediğinde dönsün.

Tekrarlara, boşluklara ve gecikmeye neden olan yaygın hatalar

Çoğu sayfalama hatası veritabanında değildir. Testte zararsız görünen küçük API kararları, istekler arasında veri değiştiğinde bozulur.

Tekrarların (veya eksik satırların) en yaygın nedeni benzersiz olmayan bir alana göre sıralamaktır. created_at ile sıralıyorsanız ve iki öğe aynı zaman damgasına sahipse, istekler arasında sıra değişebilir. Çözüm basittir: her zaman stabil bir tie-breaker ekleyin, genelde birincil anahtar; sıralamayı (created_at desc, id desc) gibi çift haline getirin.

Diğer yaygın sorun, istemcilere herhangi bir sayfa boyutu isteme izni vermektir. Bir büyük istek CPU, bellek ve yanıt sürelerini zirveye çıkararak her yönetici ekranını yavaşlatabilir. Mantıklı bir varsayılan ve katı bir maksimum seçin; istemci fazla isterse hata döndürün.

Toplamlar da zarar verebilir. Her istekte eşleşen tüm satırları saymak, özellikle filtrelerle birlikte endpoint'in en yavaş kısmı olabilir. UI toplamlara ihtiyaç duyuyorsa, yalnızca istendiğinde alın veya bir tahmin döndürün; liste kaydırmasını tam sayma ile bloklamayın.

En sık tekrarlar, boşluklar ve gecikme yaratan hatalar:

  • Benzersiz tie-breaker olmadan sıralama (kararsız sıra)
  • Sınırsız sayfa boyutları (sunucu aşırı yükü)
  • Her seferinde toplam döndürmek (yavaş sorgular)
  • Bir endpoint'te offset ve cursor kurallarını karıştırmak (istemci davranışı karışır)
  • Filtre veya sıralama değiştiğinde aynı cursor'ı yeniden kullanmak (yanlış sonuçlar)

Filtre veya sıralama değiştiğinde sayfalamayı sıfırlayın. Yeni bir filtreyi yeni bir arama olarak görün: cursor/offset'i temizleyin ve ilk sayfadan başlayın.

Yayına almadan önce hızlı kontrol listesi

Gereksinimleri güvenle değiştirin
Gereksinimler değiştiğinde biriktirilmiş teknik borç olmadan temiz kaynak kodu yeniden üretin.
Kod Üret

API ve UI yan yana çalışırken bunu bir kez çalıştırın. Çoğu sorun liste ekranı ile sunucu arasındaki sözleşmede çıkar.

  • Varsayılan sıralama stabil ve benzersiz bir tie-breaker içeriyor (örneğin created_at DESC, id DESC).
  • Sıralama alanları ve yönleri whitelist'lenmiş.
  • Maksimum sayfa boyutu uygulanmış, mantıklı bir varsayılan var.
  • Cursor tokenları opak ve geçersiz cursor'lar öngörülebilir şekilde hata veriyor.
  • Herhangi bir filtre veya sıralama değişikliği sayfalama durumunu sıfırlıyor.
  • Toplam davranışı açık: kesin, tahmini veya atlanmış.
  • Aynı sözleşme hem tablo hem infinite scroll'ü özel durum olmadan destekliyor.

Sonraki adımlar: listelerinizi standartlaştırın ve tutarlı tutun

Her gün kullanılan bir admin listesini seçin ve onu altın standartınız yapın. Tickets, Orders veya Users gibi yoğun bir tablo iyi bir başlangıçtır. O endpoint hızlı ve öngörülebilir hale gelince, aynı sözleşmeyi diğer yönetici ekranlarına kopyalayın.

Sözleşmeyi yazılı hale getirin, kısa bile olsa. API'nin ne kabul ettiğini ve ne döndürdüğünü açıkça belirtin ki UI ekibi tahmin yürütmesin ve endpoint başına farklı kurallar icat etmesin.

Her liste endpoint'ine uygulanacak basit bir standart:

  • İzin verilen sıralamalar: tam alan adları, yön ve açık bir varsayılan (artı id gibi tie-breaker).
  • İzin verilen filtreler: hangi alanlara filtre uygulanabileceği, değer formatları ve geçersiz filtrelerde ne olacağı.
  • Toplam davranışı: ne zaman bir sayım döndürürsünüz, ne zaman “bilinmiyor” döndürürsünüz ve ne zaman atlıyorsunuz.
  • Yanıt biçimi: tutarlı anahtarlar (items, sayfalama bilgisi, uygulanan sort/filters, totals).
  • Hata kuralları: tutarlı durum kodları ve okunabilir doğrulama mesajları.

AppMaster (appmaster.io) ile bu yönetici ekranlarını inşa ediyorsanız, sayfalama sözleşmesini erken standartlaştırmak faydalıdır. Aynı liste davranışını web uygulamanız ve yerel mobil uygulamalar arasında yeniden kullanabilir ve daha sonra sayfalama kenar durumlarıyla vakit kaybetmezsiniz.

SSS

Offset ve cursor sayfalamanın gerçek farkı nedir?

Offset sayfalama limit ile offset (veya page/pageSize) kullanarak satırları atlar; derin sayfalar genellikle veritabanının daha fazla satırı atlamasını gerektirdiğinden yavaşlar. Cursor sayfalama ise son görülen öğenin sıralama değerlerine dayalı bir after tokenı kullanır, bu sayede bilinen bir konumdan devam ederek ileriye doğru hızlı kalır.

Yönetici tablom neden sayfalar ilerledikçe daha yavaş hissediyor?

Çünkü 1. sayfa genelde ucuzken, 200. sayfa veritabanının çok sayıda satırı atlamasını (skip) zorunlu kılar. Sıralama ve filtreleme de varsa, sunucunun yapması gereken iş artar ve her tıklama yeni, ağır bir sorgu gibi hissedilir.

Kullanıcılar sayfalandırırken tekrarları veya eksik satırları nasıl önlerim?

Her zaman benzersiz bir tie-breaker içeren stabil bir sıralama kullanın; örneğin created_at DESC, id DESC veya updated_at DESC, id DESC. Tie-breaker yoksa aynı zaman damgasına sahip kayıtlar istekler arasında yer değiştirebilir ve bu da tekrarlar veya eksik satırlar yaratır.

Ne zaman cursor sayfalamayı tercih etmeliyim?

Kullanıcıların çoğunlukla ileriye doğru ilerlediği ve hızın önemli olduğu listeler için cursor sayfalamayı tercih edin: etkinlik günlükleri, ticketlar, siparişler ve mobil infinite scroll gibi. Cursor, bir sonraki sayfayı tam olarak görülen son öğeye dayandırdığı için eklemeler veya silinmeler karşısında daha tutarlıdır.

Offset sayfalama ne zaman hâlâ mantıklı?

“N. sayfaya atla” gerçekten bir UI özelliği ise offset sayfalama uygundur. Küçük tablolar veya nispeten durağan veri kümeleri için de offset gayet kullanışlıdır. Ancak büyük, aktif tablolar için derin sayfalarda performans ve tutarlılık sorunları görünür hale gelir.

Tutarlı bir sayfalama API yanıtı neler içermeli?

Endpoint'ler arasında tek bir yanıt biçimini koruyun ve öğeleri, sayfalama durumunu ve isteğe bağlı toplamları döndürün. Pratik bir varsayılan: items, bir page nesnesi (içinde limit, nextCursor/prevCursor veya offset) ve bir hasNext bayrağı; böylece hem web tabloları hem de mobil listeler aynı istemci mantığını kullanabilir.

Neden toplamlar sayfalamayı yavaşlatır ve daha güvenli bir varsayılan nedir?

Çünkü büyük, filtrelenmiş veri kümeleri üzerinde tam COUNT(*) yapmak isteğe bağlı olarak isteğin en yavaş kısmı olabilir ve her sayfa geçişini ağırlaştırır. Daha güvenli bir varsayılan, toplamları isteğe bağlı yapmak, yalnızca istendiğinde döndürmek veya UI sadece “Daha fazla yükle” gerektiriyorsa has_more döndürmektir.

Filtreler veya sıralama değiştiğinde cursor ne olmalı?

Filtreleri veri kümesinin bir parçası olarak görün ve cursor yalnızca o tam filtre+sort kombinasyonu için geçerli kabul edin. Kullanıcı herhangi bir filtre veya sıralama değiştirdiğinde sayfalamayı sıfırlayın; eski bir cursor'ı filtre veya sıralama değişikliğinden sonra tekrar kullanmak genellikle boş sayfalara veya kafa karıştırıcı sonuçlara yol açar.

Sayfalamayı hızlı ve öngörülebilir kılmak için sıralamayı nasıl yapmalıyım?

Sıralama alanlarını ve yönleri whitelist'leyin ve istemcilerin istenmeyen, yavaş veya kararsız sıralamalar istemesini reddedin. İndekslenmiş alanlarda sıralama yapmayı tercih edin ve her zaman son anahtar olarak benzersiz bir tie-breaker (id gibi) ekleyin, böylece istekler arasında sıralama deterministik olur.

Bir sayfalama endpoint'ini yayına almadan önce hangi korunmalar eklenmeli?

Bir maksimum limit uygulayın, filtreleri ve sıralama parametrelerini doğrulayın ve cursor tokenlarını opak (opaque) yapıp katı şekilde doğrulayın. AppMaster ile yönetici ekranları oluşturuyorsanız, bu kuralları tüm liste endpoint'lerinde tutarlı uygulamak, her ekran için özel sayfalama düzeltmeleriyle uğraşmanızı azaltır.

Başlaması kolay
Harika bir şey yaratın

Ücretsiz planla AppMaster ile denemeler yapın.
Hazır olduğunuzda uygun aboneliği seçebilirsiniz.

Başlayın
Hızlı yönetici ekranı API'leri için cursor ve offset sayfalama | AppMaster