SQL Server ve MySQL ile Sayfalama, Pagination

Created with Sketch.

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ış

Yorumunuzu ekleyin