Paginacja (wyświetlanie na stronach) pozwala na przetwarzanie dużych wyników SELECT bez nadmiernego obciążania serwera i aplikacji. Główne podejścia:
Przykład (LIMIT/OFFSET)
SELECT * FROM Orders ORDER BY OrderID LIMIT 100 OFFSET 1000;
Ten zapytanie zwraca 1011–1110 rekordy. Ale OFFSET zmusza serwer do przetworzenia i pominięcia pierwszych 1000 wierszy — dlatego przy głębokiej paginacji staje się powolne.
Przykład (metoda Keyset/Seek)
SELECT * FROM Orders WHERE OrderID > 1110 ORDER BY OrderID LIMIT 100;
Takie zapytanie szybko znajduje następną stronę, nie poświęcając zasobów na obliczanie OFFSET, szczególnie skuteczne w przypadku, gdy jest indeks na OrderID.
Pułapka: "Dlaczego paginacja za pomocą LIMIT/OFFSET może źle działać przy dużych zbiorach danych i jak to poprawić?"
Odpowiedź: Problem polega na tym, że OFFSET wymaga od serwera skanowania i sortowania wszystkich poprzednich wierszy — okazuje się, że im głębiej w stronach – tym wolniej. Optymalizacja — przejść na paginację opartą na kluczu/seek: wybierać nie według przesunięcia, ale według klucza ostatniego rekordu poprzedniej strony.
-- Otrzymujemy następną stronę według klucza SELECT * FROM Orders WHERE OrderID > @LastOrderID ORDER BY OrderID LIMIT 100;
Historia
Projekt: Marketplace, baza zamówień na przestrzeni 5 lat (50 mln wierszy)
Błąd: Używano OFFSET do paginacji zamówień starych użytkowników. Zapytania z OFFSET > 1 mln zaczęły trwać od 30 do 60 sekund. To wpłynęło na raporty i interfejs API — w rezultacie obciążenie CPU serwera wzrosło i wydłużył się czas oczekiwania w kolejce.
Historia
Projekt: Korporacyjny CRM, raporty dotyczące klientów.
Błąd: W paginacji nie uwzględniano kolejności sortowania i nie używano indeksów. Spadek wydajności i kontrola integralności zbiorów — użytkownicy otrzymywali te same wiersze na różnych stronach przy zmianach w tabeli.
Historia
Projekt: Platforma finansowa, dashboardy.
Błąd: Skomplikowane paginacje budowano przez generowany dynamiczny SQL bez zmiennych powiązanych, co prowadziło do SQL injection i problemów z utrzymywaniem transakcyjności między stronami danych.