SQL Server ve MySQL ile Sayfalama, Pagination
Merhaba, bu yazıda yeni başlayanlar ve unutanlar için (bu gruba ben de dahilim 🙂 ) verilerin sayfalanmasını yani Pagination tekniğini fazla detaya inmeden, basite indirgenmiş bir şekilde anlatmaya çalışacağım. Daha da karmaşık hale getirmemek için performans konusuna değinmeyeceğim.
Pagination / Sayfalama neredeyse her yerde karşılaşabildiğimiz gerek masaüstü, gerek mobil, gerekse web projelerinde sıklıkla kullanılan, listelenecek olan verilerin kullanıcıya parçalar halinde “çağırılmasına” hizmet eden bir tekniktir.
Pagination’daki temel amaç listelenecek olan verilerin satır sayısını sınırlandırılması esasına dayanır, yani siz verilerin tamamını değil, belli bir aralıktakileri listelersiniz.
Bunu yapabilmek için SQL Server’da iki seçeneğimiz var, duruma ve performans maliyetine göre hangisini kullanacağınız size kalmıştır. Bunlar TOP ve OFFSET & FETCH ikilisidir.
Hem TOP, hem de OFFSET & FETCH deyimleri listelenecek olan satır sayısını sınırlandırmak için kullanılabilir fakat kullanım şekilleri hangi yöntemin sizin için en iyisi olduğunu etkileyecek düzeyde birbirinden farklılıklar arzeder.
TOP ile OFFSET & FETCH arasındaki fark nedir?
TOP Deyimi
TOP, bir sorgu sonuç kümesinin (sıralamaya göre) en tepesinden (listenin başından itibaren), belirtilen sayı kadar satırı elde etmenizi sağlar. Örnekleme açısından aşağıdaki kodu inceleyebilirsiniz;
SELECT TOP 10
Ad
, Soyad
, Eposta
FROM dbo.Kisiler
Yukarıdaki kod, dbo.Kisiler tablosunda karşımıza çıkan ilk 10 satırı bize getirir. Her ne kadar ORDER BY, TOP kullanımı için gerekli değilmiş gibi gözükse de kullanılmasını tavsiye ederim. Sorgunun sonuna ORDER BY komutunu da eklersek listelenecek olan ilk 10 kayıt bizim belirttiğimiz sıralamaya uygun bir şekilde listelenecektir. Böylece beklenmedik verilerle karşılaşma riskinden de kurtulmuş oluruz.
SELECT TOP 10
Ad
, Soyad
, Eposta
FROM dbo.Kisiler
ORDER BY Soyad DESC
gibi…
TOP deyimini kullanırken istenen satır sayısını bir yüzde değeri olarak da belirtebiliriz. Diyelim ki 7305 adet satırı olan bir tablonuz var ve bu satırların sadece Yüzde 10’u ile ilgileniyorsunuz diyelim, bu durumda (7305 / 100) * 10 = 74 (yukarı yuvarlayacak şekilde) satır listelenecektir. Kullanımı ise şu şekilde;
SELECT TOP 10 PERCENT
Ad
, Soyad
, Eposta
FROM dbo.Kisiler
ORDER BY Soyad DESC
Sonuç kümesinin başından itibaren belli miktarda veri çekilmesine hizmet ettiği için çoğu durumda TOP deyimi performans açısından faydalıdır. Fakat “PERCENT” ifadesi için aynı şeyi söyleyemeyiz. Percent deyiminin kullanılması söz konusu olduğunda SQL Server arka tarafta fazladan bir kaç iş daha yapar ve bu da performansı biraz etkiler. O nedenle PERCENT deyimini performans açısından pek önermem.
OFFSET ve FETCH Deyimleri
Bu iki deyim sonuç kümesinde belli bir “aralığı” elde etmek için kullanılır. OFFSET sonuç kümesinden kaç adet satırın “es geçileceğini”, FETCH ise es geçilen satırlardan sonra kaç adet satır listeleneceğini belirtir.
ANSI ile uyumlu olan bu deyimler sanırım SQL Server 2012 ile birlikte sosyetenin cemiyet hayatına katıldılar 🙂
OFFSET’i, FETCH deyimi olmadan kullanabilirsiniz fakat FETCH tek başına kullanılamaz. Tüm bunlarla birlikte OFFSET ve FETCH aslında “ORDER BY” deyimini genişleten iki “ek” ifadedir.
Örnek olması açısından aşağıdaki kodu inceleyelim; Bu örnekte ilk 10 kayıt es geçilecek, hemen peşi sıra, devamında gelen 10 kayıt ise listelenecektir.
SELECT Ad
, Soyad
, Eposta
FROM dbo.DENEYSEL_TABLO
ORDER BY Ad, Soyad
OFFSET 10 ROWS
FETCH NEXT 10 ROWS ONLY
Aşağıdaki örnek kullanım ise “TOP 10” ifadesiyle belirtilen kullanım ile aynı sonucu üretir;
SELECT Ad
, Soyad
, Eposta
FROM dbo.DENEYSEL_TABLO
ORDER BY Ad, Soyad
OFFSET 0 ROWS --> "0" ibaresine dikkat edin !
FETCH NEXT 10 ROWS ONLY
Yukarıdaki örnekte yer alan “OFFSET 0 ROWS” ifadesi hiç bir satırın es geçilmeyeceğini belirtir.
TOP’un aksine OFFSET için bir yüzdelik dilim kullanımı yerleşik olarak desteklenen bir özellik değildir fakat bir alt sorgu kullanarak bu sorunu aşabilirsiniz.
SELECT Ad
, Soyad
, Eposta
FROM dbo.DENEYSEL_TABLO
ORDER BY Ad, Soyad
OFFSET 0 ROWS --> "0" ibaresine dikkat edin !
FETCH NEXT ( SELECT CAST(CEILING(COUNT(*) * .1) as INT) FROM dbo.Kisiler ) ROWS ONLY
Burada parantez içinde belirtilen alt sorgu yardımıyla %10’luk bir dilim elde edilebilir. Diğer varyasyonlar için hayal gücünüzü kullanabilirsiniz.
SAYFALAMA
TOP ve OFFSET deyimlerine göz attığımıza göre artık bir sayfalama örneğinin zamanı geldi sanırım. Bu noktada eğer istediğiniz şey en tepedeki kayıtlara ulaşmak ise TOP deyimini gönül rahatlığıyla kullanabilirsiniz, ORDER BY ile tatmin edici sonuçlara ulaşabilmeniz mümkün fakat amacınız belirli bir sıralamaya göre belli bir kayıt aralığını elde etmek ise OFFSET ve FETCH ikilisi sizi amacınıza çok kolay bir şekilde ulaştıracaktır. O nedenle TOP deyimini basitliği ve anlaşılırılığı kolay olduğu için örneklendirmeye gerek duymuyorum, bunun yerine OFFSET ve FETCH deyimleri için basit bir örnek vermekle konuyu tamamlayalım;
DECLARE @SayfaNo INT = 1 --> Hangi sayfayı istediğimizi bununla belirleyeceğiz
, @SatirSayisi INT = 5 --> Bir sayfada kaç adet kayıt olduğunu ise buradan belirteceğiz
SELECT Ad
, Soyad
, EPosta
FROM dbo.Kisiler
ORDER BY Soyad
, Ad
OFFSET ( @SayfaNo - 1 ) * @SatirSayisi ROWS --> Bu formül satır sayısı ile sayfa numarası arasındaki vektörel değerin hesaplanmasını, dolayısıyla es geçilecek olan toplam satır sayısını hesaplamamızı sağlar.
FETCH NEXT @SatirSayisi ROWS ONLY --> Anlaşılacağı üzere kaç satır kayıt istediğimizi burada belirttik.
MYSQL Cephesi
Konuyu MySQL açısından ele alacak olursak orada daha basit ve sade bir kullanım söz konusu. LIMIT deyimi hem TOP, hem de OFFSET & FETCH deyimlerini karşılayacak şekilde kullanılabiliyor. Bunlara basit birer örnek olması açısından aşağıdaki kodu inceleyelim;
TOP Eşdeğeri için;
SELECT Ad, Soyad, Eposta FROM Kisiler ORDER BY Soyar, Ad LIMIT 10
Yukarıdaki örnek sıralamaya göre listenin en tepesinden 10 adet satırı listeler.
OFFSET & FETCH Eşdeğeri için;
SELECT Ad, Soyad, Eposta FROM Kisiler ORDER BY Soyar, Ad LIMIT 20 , 5
Yukarıdaki örnek ise yine sıralamaya göre 20 satır es geçildikten sonra devamında gelen 5 satırı listeler.
Aşağıdaki örnek ise MySQL’de sayfalamayı parametrik hale getirebilmek için tasarlanmış bir saklı yordamı göstermektedir. Maalesef MySQL LIMIT deyiminde değişken kullanımı ile ilgili sıkıntılar çıkarıyor (En azından MySQL 5.5.27’de durum maalesef bu şekilde)
DELIMITER $
CREATE PROCEDURE `_sp_pagination`(
IN `_SayfaNo` INT,
IN `_SatirSayisi` INT
)
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
PREPARE SORGU FROM "SELECT Ad, Soyad, Eposta FROM Kisiler LIMIT ?, ?";
SET @SayfaNo = _SayfaNo - 1 * _SatirSayisi;
SET @SatirSayisi = _SatirSayisi;
EXECUTE SORGU USING @SayfaNo, @SatirSayisi;
DEALLOCATE PREPARE SORGU;
END$
Kullanımı ise şuna benzer olacaktır;
CALL _sp_pagination ( 10 -- > 10. sayfadan itibaren
, 5 -- > 5 satır getir...
)
Faydalı olması dileğiyle…
Yorum yapılmamış