Veritabanı Performans Testi: pgbench ve sysbench Kullanım Kılavuzu
Veritabanı yönetiminde “iyi çalışıyor” ile “üretim baskısı altında da iyi çalışıyor” arasındaki fark, çoğu zaman ancak bir kriz anında ortaya çıkar. PostgreSQL kurulumunu bitirip “tamam, çalışıyor” diyerek geçen her sysadmin, ileride o sunucuya saniyede yüzlerce sorgu geldiğinde ne olacağını muhtemelen hiç test etmemiştir. Ben de yıllarca öyle yaptım, ta ki üretim ortamında ciddi bir yavaşlama yaşayana kadar.
Bu yazıda pgbench ve sysbench araçlarını kullanarak veritabanı performans testlerini nasıl yapabileceğinizi, sonuçları nasıl yorumlayacağınızı ve gerçek dünya senaryolarında bu araçları nasıl kullanmanız gerektiğini aktaracağım.
Neden Yük Testi Yapmalıyız?
Bir PostgreSQL veya MySQL sunucusu kurduğunuzda, varsayılan konfigürasyon genellikle “çalışır ama optimize değil” modundadır. shared_buffers, work_mem, max_connections gibi parametreler, sunucunuzun RAM ve CPU kapasitesine göre ayarlanmalıdır. Bunu yapmadan önce bir baseline almanız, değişiklik sonrası ise tekrar test etmeniz gerekir.
Yük testi size şunları verir:
- Mevcut donanımınızın gerçek kapasitesini anlarsınız
- Konfigürasyon değişikliklerinin etkisini ölçebilirsiniz
- Darboğazları (CPU, I/O, bellek) önceden tespit edersiniz
- SLA taahhütleri için somut veri elinizde olur
- Uygulama geliştiricilerine “sunucu şu kadar QPS kaldırıyor” diyebilirsiniz
pgbench ile PostgreSQL Testi
pgbench, PostgreSQL’in kendi bünyesinde gelen bir yük test aracıdır. Kurulum gerektirmiyor, PostgreSQL ile birlikte geliyor. TPC-B benzeri bir iş yükü simüle eder; banka hesap transferlerini modelleyen tablolar üzerinde çalışır.
pgbench Kurulumu ve İlk Hazırlık
pgbench, postgresql-contrib paketinin içinde değil, doğrudan PostgreSQL ana paketinde gelir. Kontrol edelim:
# Debian/Ubuntu sistemlerde
which pgbench
pgbench --version
# Eğer yoksa
apt install postgresql-client-14
# RHEL/CentOS sistemlerde
yum install postgresql14
Test veritabanını hazırlamak için önce bir veritabanı oluşturup pgbench şemasını initialize etmeniz gerekiyor:
# Test veritabanı oluştur
createdb -U postgres pgbench_test
# pgbench şemasını oluştur, scale factor 50 = yaklaşık 5 milyon satır
pgbench -U postgres -i -s 50 pgbench_test
# Çıktı şöyle görünür:
# dropping old tables...
# creating tables...
# generating data (client-side)...
# 5000000 of 5000000 tuples (100%) done (elapsed 45.23 s, remaining 0.00 s)
# vacuuming...
# creating primary keys...
# done in 67.45 s (drop tables 0.01 s, create tables 0.01 s, ...)
-s (scale factor) parametresi önemli. Değer ne kadar büyükse, veri seti o kadar büyür. 1 = 100.000 satır, 50 = 5.000.000 satır. Testlerinizin üretim veri boyutuna yakın olması için bu değeri üretimdeki verilerinize göre seçin.
Temel pgbench Testi
# 10 bağlantı, 60 saniye süreyle test
pgbench -U postgres
-c 10
-j 2
-T 60
pgbench_test
# Parametre açıklamaları:
# -c 10 : 10 eş zamanlı istemci bağlantısı
# -j 2 : 2 thread kullan
# -T 60 : 60 saniye çalış
# -t yerine -T kullanmak süre bazlı test yapar
Çıktı şuna benzer görünür:
starting vacuum...end.
transaction type: <builtin: TPC-B (sort of)>
scaling factor: 50
query mode: simple
number of clients: 10
number of threads: 2
duration: 60 s
number of transactions actually processed: 84523
latency average = 7.099 ms
latency stddev = 4.823 ms
initial connection time = 45.678 ms
tps = 1408.624187 (without initial connection time)
Bu çıktıyı nasıl okuyacaksınız? TPS (transactions per second) değeri en kritik metriktir. Standart sapma ise tutarlılığı gösterir; eğer ortalama gecikme 7ms ama standart sapma 15ms ise, işlemlerin tutarsız sürdüğü anlamına gelir, bu da genellikle lock contention veya I/O burst’ları işaret eder.
İleri Düzey pgbench Kullanımı
Sadece varsayılan TPC-B testi yetmez. Kendi sorgularınızı test etmek için özel script yazabilirsiniz:
# custom_test.sql dosyası oluştur
cat > /tmp/custom_test.sql << 'EOF'
set account_id random(1, 100000)
SELECT abalance FROM pgbench_accounts WHERE aid = :account_id;
UPDATE pgbench_accounts SET abalance = abalance + 100 WHERE aid = :account_id;
EOF
# Bu scriptle test çalıştır
pgbench -U postgres
-c 20
-j 4
-T 120
-f /tmp/custom_test.sql
pgbench_test
Salt okunur test senaryosu için --select-only veya -S parametresi işe yarar:
# Sadece SELECT sorguları - read-only replica testleri için idealdir
pgbench -U postgres
-c 50
-j 8
-T 300
-S
pgbench_test
# Çıktıyı dosyaya kaydet ve ayrıntılı log tut
pgbench -U postgres
-c 50
-j 8
-T 300
-S
--log
--log-prefix=/tmp/pgbench_results
pgbench_test
Farklı Bağlantı Sayılarıyla Karşılaştırmalı Test
Gerçek dünyada tek bir test sayısıyla karar vermek yanlış olur. Sistemin farklı yük seviyelerindeki davranışını görmek için bir döngü yazabilirsiniz:
#!/bin/bash
# pgbench_sweep.sh - Farklı eş zamanlı bağlantı sayılarını test eder
DB="pgbench_test"
USER="postgres"
DURATION=60
THREAD_COUNT=4
echo "clients,tps,latency_avg,latency_stddev" > /tmp/pgbench_results.csv
for clients in 1 5 10 20 30 50 75 100; do
echo "Testing with $clients clients..."
result=$(pgbench -U $USER -c $clients -j $THREAD_COUNT -T $DURATION $DB 2>&1)
tps=$(echo "$result" | grep "^tps" | awk '{print $3}')
lat_avg=$(echo "$result" | grep "latency average" | awk '{print $4}')
lat_std=$(echo "$result" | grep "latency stddev" | awk '{print $4}')
echo "$clients,$tps,$lat_avg,$lat_std" >> /tmp/pgbench_results.csv
echo " -> TPS: $tps, Avg Latency: ${lat_avg}ms"
sleep 10 # Sistemin soğuması için bekle
done
echo "Sonuçlar /tmp/pgbench_results.csv dosyasına kaydedildi"
Bu script sayesinde bağlantı sayısı arttıkça TPS’in nasıl değiştiğini görürsünüz. Tipik olarak belirli bir noktadan sonra TPS düşmeli, gecikme ise artmalıdır. Bu nokta, optimal eş zamanlı bağlantı sayınızdır.
sysbench ile MySQL/MariaDB Testi
sysbench, başlangıçta MySQL için yazılmış ama zamanla çok yönlü bir performans test aracına dönüşmüş bir araçtır. Hem veritabanı hem de sistem kaynaklarını (CPU, bellek, I/O) test edebilirsiniz.
sysbench Kurulumu
# Ubuntu/Debian
apt-get install sysbench
# RHEL/CentOS - önce epel repo ekle
yum install epel-release
yum install sysbench
# Kaynak koddan derleme (en güncel sürüm için)
git clone https://github.com/akopytov/sysbench
cd sysbench
./autogen.sh
./configure
make -j4
make install
OLTP Testi için Hazırlık
sysbench ile MySQL testi yapabilmek için önce test şemasını oluşturmanız gerekiyor:
# MySQL'de test veritabanı oluştur
mysql -u root -p -e "CREATE DATABASE sbtest; CREATE USER 'sbtest'@'localhost' IDENTIFIED BY 'sbtestpass'; GRANT ALL ON sbtest.* TO 'sbtest'@'localhost';"
# sysbench tablolarını hazırla
sysbench oltp_read_write
--mysql-host=localhost
--mysql-port=3306
--mysql-user=sbtest
--mysql-password=sbtestpass
--mysql-db=sbtest
--tables=10
--table-size=1000000
prepare
# Parametre açıklamaları:
# --tables=10 : 10 ayrı tablo oluştur
# --table-size=1M : Her tabloda 1 milyon satır
# prepare : Tabloları hazırla (bir kez çalıştırılır)
OLTP Read-Write Testi
# Karma okuma-yazma testi
sysbench oltp_read_write
--mysql-host=localhost
--mysql-port=3306
--mysql-user=sbtest
--mysql-password=sbtestpass
--mysql-db=sbtest
--tables=10
--table-size=1000000
--threads=16
--time=120
--report-interval=10
run
--report-interval=10 parametresi her 10 saniyede bir anlık sonuç yazdırır. Bu özellikle uzun süren testlerde sistemin zamanla nasıl davrandığını izlemek için çok değerlidir. Başta yüksek TPS ile başlayıp zamanla düşüyorsa, buffer’ların dolduğunu veya I/O beklemesi yaşandığını gösterir.
Farklı Test Senaryoları
sysbench’in güzel tarafı, farklı iş yüklerini simüle edebilmesidir:
# Salt okunur test - read replica'lar için
sysbench oltp_read_only
--mysql-host=localhost
--mysql-user=sbtest
--mysql-password=sbtestpass
--mysql-db=sbtest
--tables=10
--table-size=1000000
--threads=32
--time=120
run
# Salt yazma testi - write-heavy uygulamalar için
sysbench oltp_write_only
--mysql-host=localhost
--mysql-user=sbtest
--mysql-password=sbtestpass
--mysql-db=sbtest
--tables=10
--table-size=1000000
--threads=16
--time=120
run
# Point select testi - index etkinliğini ölçer
sysbench oltp_point_select
--mysql-host=localhost
--mysql-user=sbtest
--mysql-password=sbtestpass
--mysql-db=sbtest
--tables=10
--table-size=1000000
--threads=64
--time=60
run
sysbench Çıktısını Anlama
Bir test çalışması tamamlandığında şuna benzer bir çıktı görürsünüz:
SQL statistics:
queries performed:
read: 2345678
write: 670194
other: 335097
total: 3350969
transactions: 167548 (1395.95 per sec.)
queries: 3350969 (27919.02 per sec.)
ignored errors: 0 (0.00 per sec.)
reconnects: 0 (0.00 per sec.)
Throughput:
events/s (eps): 1395.9521
time elapsed: 120.0239s
total number of events: 167548
Latency (ms):
min: 4.53
avg: 11.46
max: 387.23
95th percentile: 18.61
sum: 1919682.34
Burada dikkat etmeniz gereken kritik metrikler:
- 95th percentile latency: Sorguların yüzde 95’inin bu süre içinde tamamlandığı değer. 18.61ms demek, 100 sorgudan 95’i 18.61ms altında bitiyor. Maksimum değer 387ms ise bu bir sorun işareti.
- transactions per sec: Gerçek OLTP kapasiteni gösterir
- max latency: Büyük farklılıklar lock contention veya I/O gecikmesi işareti olabilir
Gerçek Dünya Senaryosu: Konfigürasyon Optimizasyonu
İşte bu araçların gerçek değeri burada ortaya çıkıyor. Teorik olarak “shared_buffers’ı artırmak performansı iyileştirir” biliyoruz ama ne kadar iyileştirir?
Önce baseline alın, ardından değişiklik yapıp tekrar test edin:
#!/bin/bash
# Konfigürasyon öncesi ve sonrası karşılaştırma scripti
PGHOST="localhost"
PGUSER="postgres"
PGDB="pgbench_test"
CLIENTS=20
THREADS=4
DURATION=120
echo "=== BASELINE TEST ==="
pgbench -h $PGHOST -U $PGUSER
-c $CLIENTS -j $THREADS -T $DURATION
$PGDB 2>&1 | tee /tmp/baseline_results.txt
echo ""
echo "Şimdi PostgreSQL konfigürasyonunu değiştirin ve yeniden başlatın"
echo "Devam etmek için Enter'a basın..."
read
echo "=== OPTİMİZASYON SONRASI TEST ==="
pgbench -h $PGHOST -U $PGUSER
-c $CLIENTS -j $THREADS -T $DURATION
$PGDB 2>&1 | tee /tmp/optimized_results.txt
echo ""
echo "=== KARŞILAŞTIRMA ==="
echo "Baseline TPS:"
grep "^tps" /tmp/baseline_results.txt
echo "Optimized TPS:"
grep "^tps" /tmp/optimized_results.txt
Bu scripti çalıştırırken aynı zamanda başka bir terminalde sistemin kaynaklarını izleyin:
# iostat ile disk I/O izle
iostat -x 2
# vmstat ile genel sistem durumu
vmstat 2
# PostgreSQL için pg_stat_activity
psql -U postgres -c "SELECT pid, wait_event_type, wait_event, query FROM pg_stat_activity WHERE state != 'idle';"
Test Sonuçlarını Yorumlarken Dikkat Edilecekler
Performans testi yaparken sık yapılan hataları ve doğru yaklaşımları şöyle özetleyebilirim:
- Warm-up süresini göz önünde bulundurun: İlk birkaç saniyedeki sonuçlar buffer’lar henüz dolmadığı için yanıltıcı olabilir. Testleri en az 60-120 saniye çalıştırın.
- Test verisini üretim boyutuna yakın tutun: 1000 satırlık tabloyla yapılan test, tüm veri RAM’e sığdığından gerçekçi değildir.
- Ağ gecikmesini hesaba katın: pgbench’i veritabanıyla aynı sunucuda mı yoksa uzak bir makinede mi çalıştırdığınız sonuçları önemli ölçüde etkiler.
- Tekrar edin ve ortalamasını alın: Tek bir test sonucuna güvenmeyin. Aynı testi birkaç kez çalıştırıp tutarlılığını kontrol edin.
- Sistemin soğuması için bekleyin: Testler arasında en az 30-60 saniye bekleyin ki önceki testin etkileri temizlensin.
- Eş zamanlı sistem izleme yapın: Testler sırasında
htop,iotop,pg_stat_bgwritergibi araçlarla nelerin tıkandığını görün.
Sonuç
pgbench ve sysbench, veritabanı altyapınızın gerçek kapasitesini anlamanın en doğrudan yoludur. Her konfigürasyon değişikliğinden önce ve sonra bu araçları çalıştırmak, kör uçuşu bırakıp veri ile karar vermeye başlamanızı sağlar.
Özellikle şu durumlarda bu testleri zorunlu görmek gerekir: yeni donanıma geçerken, PostgreSQL veya MySQL sürüm yükseltmeden önce, büyük konfigürasyon değişikliklerinde, ve önemli trafik artışı beklentisi varsa. Üretimde patlama yaşamak yerine test ortamında ölçmek, hem sizi hem de son kullanıcılarınızı korur.
Ölçmediğiniz şeyi yönetemezsiniz, ve veritabanı performansında bu söz hiç bu kadar doğru olmamıştır.
