LIMIT ve OFFSET — Sayfalama
Giriş — Her Şeyi Bir Anda Gösterme
Bir e-ticaret sitesinde 50.000 ürün var. Kullanıcı "Ürünler" sayfasına girdiğinde 50.000 ürünü tek seferde gösteremezsin — hem performans hem kullanıcı deneyimi felakete döner. Bunun yerine sayfa sayfa gösterirsin: "Sayfa 1: 1-20 ürün", "Sayfa 2: 21-40 ürün"...
İşte LIMIT ve OFFSET tam olarak bu ihtiyacı karşılar: sorgu sonucundan belirli sayıda satır al ve belirli bir noktadan başla.
🎯 Analoji: Bir kitap okuyorsun. Kitabın tamamını ezberlemiyorsun — sadece açtığın sayfayı okuyorsun. LIMIT kaç satır (paragraf) okuyacağını, OFFSET hangi sayfadan başlayacağını belirler.
LIMIT — Kaç Satır İstiyorsun?
-- İlk 5 ürünü getir
SELECT product_name, price
FROM products
LIMIT 5;
-- En pahalı 3 ürünü getir
SELECT product_name, price
FROM products
ORDER BY price DESC
LIMIT 3;+-------------------+----------+
| product_name | price |
+-------------------+----------+
| iPhone 15 Pro | 64999.99 |
| MacBook Pro 14" | 54999.99 |
| Samsung Galaxy S24| 44999.99 |
+-------------------+----------+LIMIT Olmadan ve İle Performans Farkı
-- ❌ 50.000 satırın hepsini çeker — yavaş, gereksiz bellek kullanımı
SELECT * FROM products ORDER BY price DESC;
-- ✅ Sadece ilk 10 satırı çeker — hızlı, az bellek
SELECT * FROM products ORDER BY price DESC LIMIT 10;💡 İpucu: Sorgu sonuçlarını sınırlamak hem veritabanı sunucusunu hem ağ trafiğini hem uygulamayı rahatlatır. Özellikle büyük tablolarda her zaman LIMIT kullan.
OFFSET — Nereden Başlayacaksın?
OFFSET, sonuç setinin başından kaç satır atlayacağını belirler:
-- İlk 10 ürünü atla, sonraki 10'u getir (Sayfa 2)
SELECT product_name, price
FROM products
ORDER BY product_id
LIMIT 10 OFFSET 10;
-- Alternatif syntax (LIMIT offset, count)
SELECT product_name, price
FROM products
ORDER BY product_id
LIMIT 10, 10; -- İlk 10'u atla, sonraki 10'u getir⚠️ Dikkat: İki syntax'ın parametre sırası ters: -
LIMIT 10 OFFSET 20→ 20 satır atla, 10 satır getir -LIMIT 20, 10→ 20 satır atla, 10 satır getirLIMIT ... OFFSET ...formatı daha okunabilir ve hata yapma riski düşük — bunu tercih et.
Pagination (Sayfalama) Uygulaması
Temel Sayfalama Formülü
OFFSET = (sayfa_numarasi - 1) * sayfa_basina_kayit
LIMIT = sayfa_basina_kayit-- Sayfa başına 10 ürün
-- Sayfa 1: OFFSET 0, LIMIT 10
SELECT * FROM products ORDER BY product_id LIMIT 10 OFFSET 0;
-- Sayfa 2: OFFSET 10, LIMIT 10
SELECT * FROM products ORDER BY product_id LIMIT 10 OFFSET 10;
-- Sayfa 3: OFFSET 20, LIMIT 10
SELECT * FROM products ORDER BY product_id LIMIT 10 OFFSET 20;
-- Sayfa N: OFFSET (N-1)*10, LIMIT 10Toplam Sayfa Sayısını Hesaplama
-- Toplam ürün sayısı
SELECT COUNT(*) AS total_products FROM products WHERE is_active = TRUE;
-- Sonuç: 15
-- Sayfa başına 10 ürün → 15 / 10 = 1.5 → 2 sayfa
-- CEIL fonksiyonu yukarı yuvarlar
SELECT CEIL(COUNT(*) / 10.0) AS total_pages
FROM products
WHERE is_active = TRUE;
-- Sonuç: 2Gerçek Dünya Pagination Sorgusu
-- E-ticaret ürün listesi — Sayfa 2, sayfa başına 12 ürün
-- Fiyata göre artan sıralama, sadece aktif ve stokta olan ürünler
SELECT
p.product_id,
p.product_name,
p.price,
p.stock_quantity,
c.category_name
FROM products p
LEFT JOIN categories c ON p.category_id = c.category_id
WHERE p.is_active = TRUE
AND p.stock_quantity > 0
ORDER BY p.price ASC
LIMIT 12 OFFSET 12; -- Sayfa 2
-- Toplam sonuç sayısı (pagination bilgisi için)
SELECT COUNT(*) AS total_results
FROM products
WHERE is_active = TRUE AND stock_quantity > 0;OFFSET Pagination'ın Performans Sorunu
OFFSET büyüdükçe performans düşer — çünkü veritabanı atlanan satırları da okumak zorundadır:
-- Sayfa 1: Hızlı ✅
SELECT * FROM products ORDER BY product_id LIMIT 20 OFFSET 0;
-- Sayfa 100: Yavaşlamaya başlar ⚠️
SELECT * FROM products ORDER BY product_id LIMIT 20 OFFSET 1980;
-- MySQL 1980 satırı okuyup atar, sonraki 20'yi döndürür
-- Sayfa 5000: Çok yavaş ❌
SELECT * FROM products ORDER BY product_id LIMIT 20 OFFSET 99980;
-- 99980 satır okunup atılır — büyük israf!Bu sorun büyük tablolarda (100K+ satır) ciddi performans etkisi yapar.
Çözüm: Cursor-Based Pagination (Keyset Pagination)
OFFSET yerine son görülen kaydın ID'sini kullan:
-- İlk sayfa: Son product_id bilgisi yok
SELECT * FROM products
WHERE is_active = TRUE
ORDER BY product_id ASC
LIMIT 20;
-- Son satırın product_id'si: 20
-- İkinci sayfa: product_id > 20 olanları getir
SELECT * FROM products
WHERE is_active = TRUE AND product_id > 20
ORDER BY product_id ASC
LIMIT 20;
-- Son satırın product_id'si: 40
-- Üçüncü sayfa: product_id > 40
SELECT * FROM products
WHERE is_active = TRUE AND product_id > 40
ORDER BY product_id ASC
LIMIT 20;Keyset pagination avantajları:
OFFSET kullanmadığı için her zaman hızlı (hangi "sayfa" olursa olsun)
Primary key index'ini kullanır
Arada veri eklenip silinse bile tutarlı sonuç verir
Keyset pagination dezavantajları:
"Sayfa 57'ye atla" yapılamaz (sıralı ilerlemek gerekir)
Birden fazla sütuna göre sıralamada karmaşıklaşır
"Toplam sayfa sayısı" bilgisi ayrıca hesaplanmalı
💡 İpucu: - Az sayfa (100'den az) ve "sayfaya atla" gerekiyorsa → OFFSET pagination - Çok sayfa (sonsuz scroll, API'ler) → Keyset pagination - Instagram, Twitter, Facebook gibi uygulamalar keyset pagination kullanır
LIMIT ile Tek Satır Alma
-- En pahalı ürün
SELECT product_name, price
FROM products
ORDER BY price DESC
LIMIT 1;
-- En yeni sipariş
SELECT * FROM orders ORDER BY order_date DESC LIMIT 1;
-- Rastgele bir müşteri
SELECT * FROM customers ORDER BY RAND() LIMIT 1;
-- ⚠️ ORDER BY RAND() büyük tablolarda ÇOK yavaştır!Rastgele Kayıt Alma — Performanslı Yol
-- ❌ Yavaş — tüm tabloyu sıralar
SELECT * FROM products ORDER BY RAND() LIMIT 5;
-- ✅ Hızlı — ID aralığından rastgele seç
SELECT * FROM products
WHERE product_id >= (
SELECT FLOOR(RAND() * (SELECT MAX(product_id) FROM products))
)
ORDER BY product_id
LIMIT 5;LIMIT ve UPDATE/DELETE
LIMIT sadece SELECT'te değil, UPDATE ve DELETE'te de kullanılabilir:
-- En eski 100 log kaydını sil
DELETE FROM activity_logs
ORDER BY created_at ASC
LIMIT 100;
-- İlk 10 bekleyen siparişi işleme al
UPDATE orders
SET status = 'processing'
WHERE status = 'pending'
ORDER BY order_date ASC
LIMIT 10;Gerçek Dünya Örneği — Tam Pagination Sistemi
-- Parametreler (uygulama katmanından gelir)
SET @page = 2; -- İstenen sayfa
SET @per_page = 12; -- Sayfa başına kayıt
SET @offset = (@page - 1) * @per_page;
-- Ana sorgu — sayfa verileri
SELECT
p.product_id,
p.product_name,
p.price,
c.category_name,
p.stock_quantity
FROM products p
LEFT JOIN categories c ON p.category_id = c.category_id
WHERE p.is_active = TRUE AND p.stock_quantity > 0
ORDER BY p.created_at DESC
LIMIT 12 OFFSET 12; -- @per_page OFFSET @offset
-- Meta sorgu — pagination bilgisi
SELECT
COUNT(*) AS total_items,
CEIL(COUNT(*) / 12.0) AS total_pages,
2 AS current_page, -- @page
12 AS per_page -- @per_page
FROM products
WHERE is_active = TRUE AND stock_quantity > 0;Sıkça Yapılan Hatalar
ORDER BY olmadan LIMIT kullanmak:
SELECT * FROM products LIMIT 10her çalıştırmada farklı sonuçlar verebilir. LIMIT ile birlikte her zaman ORDER BY kullan.LIMIT syntax sırasını karıştırmak:
LIMIT 10, 20→ "10 atla, 20 getir". Ama çoğu insan "10 getir, 20 atla" olarak okur.LIMIT 20 OFFSET 10formatı çok daha açık.Büyük OFFSET değerleri: Sayfa 1000 için
OFFSET 20000kullanmak performansı öldürür. Büyük veri setlerinde keyset pagination kullan.Toplam sayfa sayısını ayrı sorgulamayı unutmak: Kullanıcıya "Sayfa 2/157" göstermek istiyorsan
COUNT(*)sorgusu da gerekir. Bu ek sorgunun maliyetini göz ardı etme.OFFSET ile veri kayması: Sayfa 1'i görürken yeni kayıt eklenirse, sayfa 2'de aynı kaydı tekrar görebilirsin. Keyset pagination bu sorunu çözer.
Özet
LIMIT Nsonuç setinden N satır döndürürOFFSET Milk M satırı atlarSayfalama formülü:
OFFSET = (sayfa - 1) * sayfa_başına,LIMIT = sayfa_başınaORDER BY olmadan LIMIT kullanma — sonuçlar tutarsız olabilir
Büyük OFFSET'lerde performans düşer → keyset pagination tercih et
LIMIT 20 OFFSET 10formatıLIMIT 10, 20'den daha okunabilirLIMIT, UPDATE ve DELETE'te de kullanılabilir
Toplam sayfa sayısı için ayrı bir
COUNT(*)sorgusu gerekir
AI Asistan
Sorularını yanıtlamaya hazır