# PostgreSQL’de En İyi %N Kaydı Seçmek: Adım Adım Kılavuz
PostgreSQL veritabanınızda milyonlarca kayıt var ve bunların sadece en iyi %10’unu, en çok satış yapan %5’ini veya en aktif kullanıcıların %20’sini seçmeniz gerekiyor. Bu durumda, klasik LIMIT komutu yetersiz kalır. Bu makalede, PostgreSQL’de üst %N kaydı nasıl seçebileceğinizi, performans optimizasyonunu nasıl sağlayabileceğinizi ve karşılaşabileceğiniz zorlukları nasıl aşabileceğinizi adım adım öğreneceksiniz.
Öğrenme Yol Haritası:
* Yeni Başlayan: Temel ROW_NUMBER() ve NTILE() fonksiyonları ile basit örnekler.
* Orta Seviye: Gerçek dünya senaryoları, PERCENT_RANK() fonksiyonu ve optimizasyon ipuçları.
* İleri Seviye: Karmaşık sorgular, performans analizi, büyük veri kümeleri için stratejiler ve özel durumlar (edge case’ler).
PostgreSQL’de Temel Kavramlar: Sıralamalar ve Pencere Fonksiyonları
Veritabanınızdaki kayıtların belli bir kritere göre üst %N’ini seçmek için öncelikle kayıtları sıralamamız ve her kayda bir sıra numarası atayarak çalışmamız gerekmektedir. Bu noktada PostgreSQL’in güçlü pencere fonksiyonlarından faydalanacağız. En yaygın kullanılan fonksiyonlar ROW_NUMBER(), RANK(), NTILE() ve PERCENT_RANK()‘tir.
ROW_NUMBER() her satıra benzersiz bir sıra numarası atar. RANK() ise aynı sırada yer alan satırlara aynı sıra numarasını atar. NTILE(n) ise verileri n eşit parçaya bölerek her parçaya bir sıra numarası atar. PERCENT_RANK() ise her satırın yüzdelik dilimini hesaplar.
Örneğin, bir ürün satış tablonuz olduğunu ve en çok satan ürünlerin %20’sini seçmek istediğinizi varsayalım. Öncelikle ürünleri satış miktarına göre sıralayıp daha sonra ROW_NUMBER() veya NTILE() ile her ürüne bir sıra numarası atayacağız. Sonrasında ise bu sıra numarasını veya yüzdelik dilimini kullanarak üst %20’yi filtreleyeceğiz.
PostgreSQL’de Üst %N Kaydı Seçme: Adım Adım Uygulama
Yeni Başlayan:
Öncelikle basit bir örnek ile başlayalım. Bir urunler tablomuz olsun ve bu tabloda urun_adi ve satis_miktari sütunları bulunsun. En çok satan ürünlerin %25’ini seçmek için aşağıdaki sorguyu kullanabiliriz:
SELECT urun_adi, satis_miktari
FROM (
SELECT urun_adi, satis_miktari, ROW_NUMBER() OVER (ORDER BY satis_miktari DESC) as rn, COUNT(*) OVER () as total_count
FROM urunler
) as ranked_urunler
WHERE rn <= (total_count * 0.25)::BIGINT;
Bu sorgu öncelikle ürünleri satış miktarına göre azalan sırada sıralar ve her ürüne bir sıra numarası (rn) atar. total_count ise toplam kayıt sayısını hesaplar. Sonrasında ise sıra numarası toplam kayıt sayısının %25’inden küçük veya eşit olan kayıtları seçer. ::BIGINT dönüşümü, olası ondalık sonuçları tam sayıya çevirir.
Orta Seviye:
Şimdi daha gerçekçi bir senaryo ele alalım. Bir e-ticaret sitesinin müşteri siparişlerini içeren bir tablosu olsun. Bu tabloda musteri_id, siparis_tarihi, siparis_tutari gibi sütunlar bulunmaktadır. Son 6 ayda en yüksek sipariş tutarına sahip müşterilerin %10’unu bulmak isteyelim.
SELECT musteri_id, SUM(siparis_tutari) as toplam_siparis_tutari
FROM siparisler
WHERE siparis_tarihi >= NOW() - INTERVAL '6 months'
GROUP BY musteri_id
ORDER BY toplam_siparis_tutari DESC
LIMIT (SELECT COUNT(*) * 0.1 FROM (SELECT musteri_id, SUM(siparis_tutari) as toplam_siparis_tutari FROM siparisler WHERE siparis_tarihi >= NOW() - INTERVAL '6 months' GROUP BY musteri_id) as subquery);
Bu sorgu öncelikle son 6 aylık siparişleri toplar, müşterileri toplam sipariş tutarına göre sıralar ve daha sonra alt sorgu ile toplam kayıt sayısının %10’unu hesaplayarak LIMIT ile üst %10’u seçer. Bu yaklaşım daha okunabilir ve anlaşılırdır.
İleri Seviye:
Büyük veri kümeleri için performans optimizasyonu çok önemlidir. İndeksler, materyalize görünümler ve doğru pencere fonksiyonlarının seçimi performansı büyük ölçüde etkiler. Örneğin, NTILE() fonksiyonu büyük veri kümeleri için daha verimli olabilir. Ayrıca, WHERE koşullarını optimize etmek ve gereksiz hesaplamaları önlemek için sorguları dikkatlice inceleyin. Performans analizi için EXPLAIN ANALYZE komutunu kullanabilirsiniz. [Fatih Soysal’ın blogu](https://fatihsoysal.com) PostgreSQL performans optimizasyonu konusunda daha fazla bilgi sunmaktadır.
Performans Optimizasyonu İpuçları
* İndeksleme: ORDER BY ve WHERE koşullarında kullanılan sütunlar için uygun indeksler oluşturun.
* Materyalize Görünümler: Sık kullanılan alt sorguları materyalize görünümler olarak saklayın.
* Pencere Fonksiyonu Seçimi: Büyük veri kümeleri için NTILE() fonksiyonunu tercih edin.
* Parçalama (Partitioning): Büyük tabloları mantıksal olarak parçalara ayırın.
* EXPLAIN ANALYZE Kullanımı: Sorgu performansını analiz edin ve iyileştirmeler yapın.
Gerçek Dünya Senaryoları ve Vaka Analizleri
* E-ticaret: En çok satan ürünlerin %10’unu belirlemek.
* Finans: En yüksek getiri sağlayan portföylerin %5’ini seçmek.
* Sosyal Medya: En aktif kullanıcıların %20’sini belirlemek.
* Sağlık: En yüksek riskli hastaların %15’ini tespit etmek.
Sonuç
PostgreSQL’de üst %N kaydı seçmek için çeşitli yöntemler mevcuttur. Seçtiğiniz yöntem veri kümesinin büyüklüğü, performans gereksinimleri ve sorgu karmaşıklığına bağlı olarak değişebilir. Bu makalede ele alınan yöntemler ve ipuçları, PostgreSQL veritabanınızda üst %N kaydı seçerken karşılaşabileceğiniz zorlukları aşmanıza yardımcı olacaktır.
Sıkça Sorulan Sorular:
1. ROW_NUMBER() ve RANK() arasındaki fark nedir? ROW_NUMBER() her satıra benzersiz bir sıra numarası atarken, RANK() aynı sırada yer alan satırlara aynı sıra numarasını atar.
2. Büyük veri kümeleri için en uygun yöntem hangisidir? Büyük veri kümeleri için NTILE() ve uygun indeksleme ile materyalize görünümler kullanılması önerilir.
3. Performans sorunlarını nasıl tespit edebilirim? EXPLAIN ANALYZE komutunu kullanarak sorgu performansını analiz edebilirsiniz.
4. PERCENT_RANK() fonksiyonu nasıl kullanılır? PERCENT_RANK() her satırın yüzdelik dilimini hesaplar ve üst %N’i belirlemek için kullanılabilir.
5. Parçalama (Partitioning) nasıl yardımcı olur? Parçalama, büyük tabloları mantıksal olarak parçalara ayırarak sorgu performansını artırır.
Yazar: Fatih Soysal
