Menu

SQLite LIMIT ve OFFSET ile Sayfalama ve Satır Sınırlama

SQLite'ta LIMIT ve OFFSET nasıl çalışır? Satır sınırlama, satır atlama, güvenli sayfalama ve büyük tablolarda dikkat etmeniz gereken performans tuzağı.

Bu sayfada çalıştırılabilir editörler var — düzenle, çalıştır ve sonucu anında gör.

LIMIT ile Dönen Satır Sayısını Sınırlama

LIMIT, SQL'deki en basit ayar düğmesi: SQLite'a "bana en fazla şu kadar satır ver" demenin yolu. Bir SELECT sorgusunun sonuna eklediğinde geriye en fazla belirttiğiniz sayıda satır döner — daha fazlası asla, ama tabloda yeterli satır yoksa daha azı gelebilir.

İlk üç satırı geri alırsınız. Peki tam olarak hangi üç satır? İşin püf noktası burada: ORDER BY kullanmadığında SQLite işine gelen sırayı seçer. Bugün ekleme sırasına göre gelir, yarın bir güncelleme ya da indeks değişikliğinden sonra başka bir sırada gelebilir. Tek başına LIMIT, "şuna bir göz atayım" demek için yeterli; ama sıra önemli olmaya başladığı an, bunu açıkça belirtmeniz şart.

OFFSET ile baştan satır atlama

LIMIT ile OFFSET'i birlikte kullanınca sonuç kümesinin ortasından bir dilim alabilirsiniz. OFFSET k ilk k satırı atar; ardından LIMIT n kalanlardan en fazla n satır döndürür. Bu ikili, SQLite sayfalama yaparken en çok başvurduğunuz yapıdır.

Yani "ilk iki satırı atla, sonraki iki satırı getir" — sıralanmış sonuçtaki 3. ve 4. satırlar. Zihninizde şöyle canlandırın: WHERE filtreler, ORDER BY sıralar, OFFSET atlar, LIMIT üst sınır koyar. Çalışma sırası bu ve hepsinin önemi var.

Sayfalama için ORDER BY Şart

LIMIT ve OFFSET denilince akla ilk gelen kullanım sqlite sayfalama: uzun bir listeyi mesela 20'şer satırlık sayfalara bölmek. 1. sayfa LIMIT 20 OFFSET 0, 2. sayfa LIMIT 20 OFFSET 20, böyle gider.

Dikkat etmeniz gereken iki nokta var. Birincisi, ORDER BY olmazsa olmaz — onsuz "2. sayfa" diye bir şeyden söz edemezsiniz, çünkü satırlar her sorguda farklı sıralarda gelebilir. İkincisi, sıralama anahtarına id alanını da eşitlik bozucu olarak ekledik. İki gönderinin created_at değeri aynıysa, sıralamayı deterministik hale getirecek tekil bir sütuna ihtiyacınız var; yoksa satırlar yer değiştirebilir ve bir kayıt sayfalar arasında kayabilir.

Pratik kural: ya tekil bir sütuna göre sıralayın ya da sıralama sütununuza tekil bir eşitlik bozucu ekleyin.

Kısayol: LIMIT n, m

SQLite, MySQL ile geriye dönük uyumluluk için eski virgüllü söz dizimini de destekler: LIMIT offset, count. Anlamı LIMIT count OFFSET offset ile aynıdır, ama sıra ters olduğu için kolayca yanlış okunabilir.

-- Bu ikisi eşdeğerdir:
SELECT * FROM books LIMIT 10 OFFSET 20;
SELECT * FROM books LIMIT 20, 10;     -- önce offset, sonra adet

İkinci form kısa ve öz duruyor ama ilk sayının limit olduğunu sananları çoğu zaman yanıltıyor. Bence LIMIT n OFFSET k kullanımına sadık kalın — hem açık hem de soldan sağa doğal okunuyor.

LIMIT Olmadan OFFSET: LIMIT -1 Numarası

OFFSET'i tek başına kullanamazsınız — SQLite'ın söz dizimi, onun mutlaka bir LIMIT'in arkasından gelmesini şart koşuyor. Peki "ilk 10 satırı atla, sonrasında ne varsa getir" demek istediğinizde ne yapacaksınız? Burada yaygın çözüm LIMIT -1 yazmak; SQLite bunu "üst sınır yok" şeklinde yorumluyor.

Negatif değer veren herhangi bir LIMIT aynı işi görür, ama yerleşik kullanım -1 şeklindedir. Bunu daha çok, sonuç kümesini sayfa sayfa dolaşan ve son parti için "kalanların hepsini ver" sorgusuna ihtiyaç duyan scriptlerde görürsünüz.

OFFSET'in Performans Tuzağı

Kimsenin başınıza gelene kadar söylemediği şey şu: OFFSET, SQLite'a iş atlatmaz; sadece çıktı atlatır. 10.001 ile 10.020 arasındaki satırları döndürmek için motor, sonuç üretmeye başlamadan önce ilk on bin satırı dahili olarak yine de gezer. Küçük offset değerleri bedava sayılır; ama on binler, yüz binler mertebesindeki offset'lerde yavaşlama gözle görülür hale gelir.

Derin sayfalamada standart çözüm keyset pagination (anahtar tabanlı sayfalama) yöntemidir: "N satır atla" yerine son satırın sıralama anahtarını aklında tut ve "bu satırdan sonrakileri getir" diye sor.

Her sayfa, önceki kayıtları tek tek tarayıp atlamak yerine indeks üzerinden doğrudan ilgili noktaya gider. Bunun bir bedeli var tabii: doğrudan "47. sayfa"ya atlayamazsınız; veride yalnızca ileri yönde ilerleyebilirsiniz. Ama sonsuz kaydırmalı akışlar ve API imleçleri için tam da istediğiniz davranış budur.

OFFSET tabanlı sayfalama, yönetim panelleri ve küçük sonuç kümeleri için gayet iş görür. Ancak sınırsız büyüyebilen veri söz konusuysa keyset pagination'a (anahtar tabanlı sayfalama) yönelin.

Uçtan Uca Bir Örnek

Şimdi her şeyi bir araya getirelim — filtreleme, sıralama ve eşitlik durumlarını çözen belirleyici bir tiebreaker içeren sayfalı bir sorgu:

Sonuçları ofis ürünleriyle sınırla, fiyata göre artan sırada diz, eşitlik durumunda isme göre ayır ve ilk iki kaydı al. 2. sayfa için OFFSET 0 yerine OFFSET 2 yaz. Sorgu kısa ama her bir ifade hak ettiği yeri dolduruyor.

Sırada: DISTINCT

LIMIT kaç satırın döneceğini belirler; DISTINCT ise tekrar eden satırların hiç dönüp dönmeyeceğini kontrol eder. SELECT cephaneliğinde sıradaki durağımız bu — ilk bakışta basit görünüp kolayca yanlış kullanılabilen bir ifade. Detaylar bir sonraki sayfada.

Sıkça Sorulan Sorular

SQLite'ta LIMIT ne işe yarar?

LIMIT n, bir SELECT sorgusunun döndüreceği satır sayısını en fazla n ile sınırlar. WHERE, GROUP BY ve ORDER BY'dan sonra çalışır; yani sorgunun taradığı satırları değil, son sonuç kümesini kısıtlamış olursunuz. Örneğin SELECT * FROM users LIMIT 10 size en fazla 10 satır döndürür.

SQLite'ta OFFSET, LIMIT ile birlikte nasıl çalışır?

OFFSET k, LIMIT saymaya başlamadan önce sonucun ilk k satırını atlar. Yani LIMIT 10 OFFSET 20 size 21'inci satırdan 30'uncuya kadar olanları getirir. SQLite o atlanan satırları yine de iç tarafta dolaşmak zorunda — büyük OFFSET değerlerinde sorguların yavaşlamasının sebebi de tam olarak bu.

SQLite'ta LIMIT olmadan OFFSET kullanılabilir mi?

Doğrudan kullanılamaz — OFFSET sadece bir LIMIT cümlesinin parçası olarak geçerli. Çözüm LIMIT -1 OFFSET k yazmak: buradaki -1, 'üst sınır yok' anlamına geliyor. Yani SQLite k satırı atlıyor ve geri kalan her şeyi döndürüyor. Akılda tutulması gereken küçük bir SQLite tuhaflığı.

Sayfalama sorgularında ORDER BY neden şart?

ORDER BY yoksa SQLite satırları istediği sırada döndürmekte serbest ve bu sıra her sorguda değişebilir. Bu durumda sayfalama bozulur — aynı satır hem 1. sayfada hem 3. sayfada çıkabilir, ya da hiç görünmeyebilir. LIMIT/OFFSET'i her zaman benzersiz ve kararlı bir sütuna göre yapılan ORDER BY ile birlikte kullanın.

Coddy programming languages illustration

Coddy ile kodlamayı öğren

BAŞLA