Offset Pagination a mobilfejlesztésben: mi ez és hogyan valósítsuk meg

Szerző: IT Sectr Megjelenés: 2026-03-11 Olvasási idő: 10 perc

Offset Pagination — lapozás eltolással — adatok oldalankénti betöltésének módszere HTTP API-n keresztül. A kliens átadja az offset (eltolás a kezdettől) és limit (oldalméret) paramétereket, a szerver pedig az offset pozíciótól kezdve adja vissza a rekordokat. A REST API Tutorial szerint ez a megközelítés széles körben használatos a RESTful szolgáltatásokban az implementáció egyszerűsége miatt. Nagy adatmennyiségeknél azonban az offset-lapozás veszít a teljesítményből a tábla teljes beolvasása miatt a kívánt pozícióig.

Főbb pontok

  • Offset Pagination — lapozási módszer, ahol a szerver kihagy N rekordot és visszaadja a következő M-et.
  • Egyszerűsége miatt a REST API és mobil kliensek szabványává vált.
  • Kihagyás problémája — rekordok beszúrásakor a kérések között a felhasználó duplikátumokat lát.
  • Adatok ugrálása — rekordok törlése az oldalak eltolódásához és tartalomvesztéshez vezet.
  • Cursor-based lapozás ezeket a problémákat az eltolás helyett az utolsó rekordra mutató mutató segítségével oldja meg.

Mi az Offset Pagination?

Offset Pagination — az adatok oldalakra osztásának módszere, ahol a kliens kérése két paramétert tartalmaz: offset (hány rekordot kihagyni) és limit (hány rekordot visszaadni). A szerver végrehajt egy SQL lekérdezést OFFSET és LIMIT utasításokkal, kihagyja a megadott számú sort, és visszaadja a rögzített méretű eredményhalmazt.

A módszer a relációs adatbázisokban jelent meg, mint a legegyszerűbb módja az oldalak közötti navigáció megszervezésének, és a REST architektúra fejlődésével került át a HTTP API-ba. Az Offset Pagination nem igényel állapottárolást a szerveren — minden kérés független és tartalmazza a lekéréshez szükséges összes információt.

A Postman (2025) API-tervezési kutatása szerint az offset-lapozást a nyilvános REST API-k 72%-a használja, ami az ismert teljesítménykorlátozások ellenére domináns szabvánnyá teszi nagy adatmennyiségek esetén.

A kérés és válasz szerkezete

Egy tipikus REST kérés Offset Pagination-nel tartalmazza a offset és limit lekérdezési paramétereket. A válasz tartalmazza a kért oldal rekordjainak listáját és metaadatokat a navigációs felület felépítéséhez.

A limit paraméter korlátozza a visszaadott rekordok számát és védi a szervert és a klienst a túlzott terheléstől. Tipikus limit értékek — 10-től 50 rekordig oldalanként, az adatok összetettségétől függően.

kotlin
data class PageRequest(
    val offset: Int,
    val limit: Int
)

data class PageResponse<T>(
    val items: List<T>,
    val total: Int,
    val hasMore: Boolean
)

fun RetrofitApi.fetchPage(request: PageRequest): Call<PageResponse<Item>>

Hogyan működik az Offset Pagination

Offset Pagination egy SQL lekérdezéssé alakul át OFFSET és FETCH NEXT (vagy LIMIT MySQL/SQLite esetén) konstrukciókkal. Az adatbázis-szerver beolvassa a táblát, kihagyja az offset-nek megfelelő számú sort, és visszaadja a következő limit sort. Minél nagyobb az offset, annál tovább tart a lekérdezés.

A teljesítményprobléma azzal függ össze, hogy az adatbázis nem tud közvetlenül az offset pozícióra ugrani — el kell olvasnia és el kell dobnia az összes előző sort. Offset = 100000 és limit = 20 esetén a DBMS 100020 sort olvas be, és csak 20-at ad vissza.

SQL lekérdezés a motorháztető alatt

SQL — a nyelv, amelyen a szerver az offset-lapozást végrehajtja. PostgreSQL-ben és MySQL-ben a LIMIT, SQL Server-ben és Oracle-ben az OFFSET...FETCH használatos. A különböző DBMS-ek a maguk módján optimalizálják ezt a lekérdezést, de az alapvető beolvasási probléma ugyanaz marad.

sql
SELECT id, title, created_at
FROM articles
ORDER BY created_at DESC
OFFSET 100000 ROWS
FETCH NEXT 20 ROWS ONLY;

Konzisztencia probléma

Adatok konzisztenciája — az Offset Pagination fő hátránya dinamikus halmazokkal való munka során. Ha a felhasználó két kérése között egy új rekord kerül a tábla elejére, az összes létező rekord eltolódik. A felhasználó duplikátumokat vagy kihagyásokat lát.

Képzeljünk el egy 100 rekordból álló táblát limit = 20 értékkel. Az 1. oldalon a felhasználó az 1-20 rekordokat látja. Az adminisztrátor hozzáad 5 új rekordot. A 2. oldalon a felhasználó a várt 21-40 helyett a 26-45 rekordokat látja — a 21-25 rekordok kimaradnak, és az előző halmaz 21-25 rekordjai duplikálódnak az 1. oldalon.

Offset vs Cursor-based: a megközelítések összehasonlítása

Cursor-based pagination — alternatíva az Offset Pagination-re, amely az aktuális oldal utolsó rekordjára mutató mutatót használ. Numerikus eltolás helyett a kliens átadja az utolsó kapott rekord azonosítóját, a szerver pedig visszaadja a következő N rekordot utána.

A cursor-based megközelítés megoldja a konzisztencia problémát: a kurzor pozíciója nem változik beszúrások vagy törlések esetén, mivel a kurzor egy konkrét rekordra hivatkozik, nem pedig egy pozícióra. Azonban bonyolultabb megvalósítani — egyedi rendezhető mezőt igényel (általában ID vagy timestamp).

ParaméterOffset PaginationCursor-based Pagination
EgyszerűségMagas — két numerikus paraméterKözepes — kurzor kódolása szükséges
KonzisztenciaAlacsony — duplikátumok beszúráskorMagas — kurzor nem függ a változásoktól
TeljesítményCsökken az offset növekedésévelStabil bármilyen mennyiségnél
Ugrás oldalraIgen — bármely oldalra ugorhatunkNem — csak szekvenciális navigáció
Alkalmas<10K rekord táblák, UI oldalszámokkalFeed-ek, végtelen görgetés, nagy halmazok

A megközelítések közötti választás a felhasználó felületi követelményeitől függ. Ha oldalszámokkal való navigációra és közvetlen ugrásra van szükség — az Offset Pagination egyszerűbb. Végtelen görgetéshez vagy hírfolyamokhoz a kurzorok az előnyösebbek.

Keyset pagination

Keyset pagination — a cursor-based megközelítés egy változata, ahol a szűrés egyedi kulcs alapján történik WHERE segítségével az OFFSET helyett. Az SQL lekérdezés a WHERE id > lastId feltételt használja, ami lehetővé teszi az adatbázis számára, hogy indexet használjon az eldobott sorok beolvasása nélkül.

A PostgreSQL Wiki szerint a keyset pagination 100-1000-szer gyorsabban hajtódik végre, mint az offset lekérdezés nagy eltolásoknál, mivel az indexbeolvasás helyettesíti a tábla teljes bejárását. Hátrány — nem lehet tetszőleges oldalra ugrani szekvenciális bejárás nélkül.

Mikor használjuk az Offset Pagination-t

Offset Pagination optimális kis és közepes adathalmazokhoz (10000 rekordig), ahol a felhasználónak oldalszámokkal ellátott felületre van szüksége. Tipikus forgatókönyvek — admin panelek, rendelési listák, szűréssel és oldalankénti lapozással ellátott katalógusok.

Mobil alkalmazások esetén az offset-lapozás akkor megfelelő, amikor történeti adatokat töltünk be, ahol új rekordok beszúrása ritka vagy lehetetlen — például a felhasználó rendelési előzményei, befejezett feladatok listája, tranzakciós archívum. Ezekben a forgatókönyvekben a konzisztencia probléma nem merül fel.

Nem ajánlott az Offset Pagination használata közösségi média feed-ek, kommentlisták, chat-ek és más gyakori beszúrásokkal rendelkező dinamikus halmazok esetén. Ezekben az esetekben a rekordok kihagyása és duplikálódása rontja a felhasználói élményt, és további deduplikációs logikát igényel a kliens oldalon.

Hibrid megközelítés

Hibrid lapozás kombinálja az offset-et és a kurzort: az első kérés offset-et használ a kezdő oldal megjelenítésére, a következők pedig kurzort a végtelen görgetés betöltéséhez. Ezt a megközelítést az Instagram és a Twitter alkalmazza, ahol az első oldal kurzoron keresztül töltődik be, de az offset-et a pozíció kiszámításához használják az előző nézetbe való visszatéréskor.

A hibrid megközelítés megvalósítása megköveteli a felhasználó virtuális pozíciójának tárolását a kliens oldalon és két lapozási mechanizmus összehangolását a szerveren. Az Instagram Engineering blogja szerint csapatuk cursor-based lapozást használ egy további startCursor mezővel, amely az offset-et helyettesíti a kezdeti betöltéshez.

Offset Pagination mobil alkalmazásokban

Mobil alkalmazások az Offset Pagination-t a Retrofit/OkHttp-val Androidon és az URLSession/Combine-nal iOS-en használják. A tipikus minta — a következő oldal betöltése a lista végére görgetéskor RecyclerView.OnScrollListener vagy UICollectionView prefetching segítségével.

Az offset-lapozás megvalósítása mobil kliensen három komponenst foglal magában: lapozáskezelő (tárolja az aktuális offset-et és a hasMore-t), lista adapter (megjeleníti az elemeket és a betöltés jelzőjét) és repository (végrehajtja a kéréseket és kezeli a hibákat). Az Android Jetpack kínálja a Paging 3 Library-t, amely mind az offset, mind a cursor-based lapozást támogatja a dobozból kivéve.

Megvalósítás Kotlin-nel és Paging 3-mal

Paging 3 — Android Jetpack könyvtár adatok oldalankénti betöltéséhez. Beágyazza a lapozás logikáját, beleértve az offset követését, a betöltési állapot kezelését és az automatikus betöltést görgetéskor. A PagingSource határozza meg a következő és előző oldal kulcsait.

kotlin
class OffsetPagingSource(
    private val api: ApiService,
    private val limit: Int = 20
) : PagingSource<Int, Item>() {

    override suspend fun load(
        params: LoadParams<Int>
    ): LoadResult<Int, Item> {
        val offset = params.key ?: 0
        return try {
            val response = api.getItems(offset, limit)
            LoadResult.Page(
                data = response.items,
                prevKey = null,
                nextKey = if (response.hasMore) offset + limit else null
            )
        } catch (e: Exception) {
            LoadResult.Error(e)
        }
    }
}

PagingSource határozza meg a prevKey és nextKey kulcsokat az oldalnavigációhoz. Offset-lapozásnál a prevKey mindig null (nem lehet az előző oldalra lépni előzmények mentése nélkül), a nextKey pedig minden betöltéskor limit-tel nő, amíg a szerver hasMore = false értéket nem ad vissza. Ez egy egyszerű és kiszámítható modell mobil listákhoz.

Gyakori hibák az Offset Pagination-nél

Első hiba — a rekordok sorrendjére hagyatkozni rendezés nélkül. Az Offset Pagination megköveteli a stabil ORDER BY rendezést egy egyedi mezőn. Enélkül a DBMS tetszőleges sorrendben adhatja vissza a rekordokat, ami véletlenszerű duplikátumokhoz és kihagyásokhoz vezet az oldalak között.

Második hiba — az offset használata az oldalszám kiszámításához a felületen. A page = offset / limit + 1 képlet csak azzal a feltétellel működik, hogy egyetlen rekord sem lett törölve vagy hozzáadva a betöltések között. Dinamikus adatoknál az oldalszám pontatlanná válik, és a felhasználó hibás információkat lát.

Harmadik hiba — a nagy offsetű lekérdezések időtúllépéseinek figyelmen kívül hagyása. 100000 feletti offset esetén a lekérdezés több tíz másodpercig is eltarthat, blokkolva a felületet és fogyasztva a szerver erőforrásait. Javasolt a maximális offset érték beállítása API szinten (például 10000), és a cursor-based lapozás használata nagy mennyiségekhez.

Negyedik hiba — a total count hozzáadásának elmulasztása a válaszhoz. A rekordok teljes száma nélkül a kliens nem tudja megjeleníteni az oldalak számát és megvalósítani a számozott lapozást. A COUNT(*) kiszámítása nagy táblákon azonban szintén költséges — 100000 rekord feletti halmazokhoz használjon közelítő becsléseket vagy korlátozza a maximális total értéket.

Gyakran Ismételt Kérdések

Miben különbözik az Offset Pagination a Cursor-based-től?

Az offset numerikus eltolást (offset) használ a rekordok kihagyására, míg a kurzor az előző oldal utolsó rekordjára mutató mutatót. Az offset egyszerűbb megvalósítani, de szenved a duplikátumoktól beszúráskor és a teljesítményvesztéstől nagy eltolásoknál. A kurzor stabil az adatok bármilyen változásánál.

Mikor működik rosszul az Offset Pagination?

Az offset lapozás nem hatékony 10000 rekord feletti offset esetén a tábla teljes beolvasása miatt. Szintén alkalmatlan dinamikus halmazokhoz (feed-ek, chat-ek), ahol új rekordok jelennek meg a kérések között — a felhasználó kihagyásokat és duplikátumokat lát navigáció közben.

Milyen limit optimális az Offset Pagination-hez?

Az optimális limit a rekord méretétől és a hálózati sebességtől függ — 10-től 50 elemig oldalanként. Nagy képeket tartalmazó listákhoz használjon limit = 10-15-öt, szöveges adatokhoz — 20-50-et. Mindig engedje meg a kliensnek, hogy megadja a saját limitjét egy maximális korláttal a szerveren (általában 100).

Hogyan küzdjünk a duplikátumok ellen az Offset Pagination-nél?

A duplikátumok elleni küzdelemhez használjon deduplikációt a kliens oldalon egyedi ID alapján, alkalmazzon stabil rendezést egyedi mezőn, vagy váltson cursor-based lapozásra. Az Android Paging 3 támogatja a kulcsot a lista elemek automatikus deduplikációjához.

Használható az Offset Pagination GraphQL-lel?

Igen, a GraphQL támogatja az offset-lapozást az offset és limit argumentumokon keresztül a lekérdezésben, bár a Relay specifikáció a cursor-based megközelítést ajánlja. Az Apollo GraphQL és a Relay könyvtárak beépített támogatást nyújtanak az offset-lapozáshoz automatikus oldalállapot-kezeléssel.

Összefoglalás

  • Offset Pagination — lapozási módszer offset és limit paraméterekkel a rekordok kihagyására és korlátozására az API-ból történő oldalankénti adatbetöltés során.
  • Egyszerűsége és a kérések függetlensége az Offset Pagination-t a REST API-k 72%-ának szabványos megközelítésévé teszi (Postman, 2025 adatok).
  • Teljesítménye 10000 feletti offset esetén csökken a tábla kívánt pozícióig történő beolvasása miatt — az adatbázis az összes eldobott sort elolvassa.
  • Konzisztencia probléma — rekordok beszúrása és törlése a lekérdezések között duplikátumokhoz és kihagyásokhoz vezet az oldaleredményekben.
  • Cursor-based lapozás megoldja az Offset Pagination problémáit az utolsó rekordra mutató mutató segítségével a numerikus eltolás helyett.
  • Hibrid megközelítés kombinálja az első oldal offset-jét a kurzoros betöltéssel a végtelen görgetéshez mobil alkalmazásokban.
  • Javaslat — használja az Offset Pagination-t statikus halmazokhoz 10000 rekordig, és váltson kurzorokra nagy mennyiségek és dinamikus adatok esetén.

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is