• 25.08.2026 09:23:37
  • Admin Admin

Veritabanı optimizasyonu yalnızca SELECT gecikmesini azaltmak değildir. PostgreSQL, SQL Server ve MongoDB’de indekslerin INSERT/UPDATE maliyetini ölçmeyi, gereksiz indeksleri güvenle kaldırmayı ve önce-sonra doğrulamayı inceliyoruz.

Database Indexleme: Yazma Maliyetini Ölçüp İndeksleri Budamak

Veritabanı performans ayarlama için önce yazma yükünü taban çizgisine oturtun

Bir indeks önerisini kabul etmeden önce iki metriği aynı zaman aralığında kaydedin: sorgu gecikmesi ve yazma başına değişen fiziksel iş. PostgreSQL’de pg_stat_statements ile çağrı sayısı, ortalama süre ve blok okuma/yazma değerlerini; tablo ve indeks boyutlarını ise pg_relation_size ile toplayın. Aşağıdaki sorguyu dağıtım öncesi ve sonrasında, benzer trafik pencerelerinde çalıştırın. Salt ortalama süreye bakmak yanıltıcıdır: az sayıda yavaş sorgu p95’i bozarken ortalama sabit kalabilir; bu nedenle uygulama APM’inden p50/p95/p99 değerlerini de aynı etiketle eşleştirin.

SELECT queryid,
       calls,
       round(mean_exec_time::numeric, 2) AS mean_ms,
       round((total_exec_time / NULLIF(calls, 0))::numeric, 2) AS avg_ms,
       shared_blks_read,
       shared_blks_written
FROM pg_stat_statements
WHERE query ILIKE '%INSERT INTO orders%'
   OR query ILIKE '%UPDATE orders%'
ORDER BY total_exec_time DESC
LIMIT 20;

SELECT c.relname,
       pg_size_pretty(pg_relation_size(c.oid)) AS table_size,
       pg_size_pretty(pg_indexes_size(c.oid)) AS indexes_size
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname = 'public' AND c.relname = 'orders';

Database indexleme neden INSERT ve UPDATE yolunu uzatır?

İndeksin gerçekten okuma yolunda seçilip seçilmediğini, oluşturma komutunun başarılı olmasından ayrı değerlendirin. PostgreSQL’de idx_scan = 0 tek başına silme kararı değildir: istatistikler yeniden başlatma sonrası sıfırlanmış olabilir, benzersizlik kısıtı indekse dayanıyor olabilir veya indeks nadir fakat kritik bir sorgu için gerekli olabilir. En az bir iş döngüsü boyunca izleyin; ardından indeks tanımını, boyutunu ve kullanımını birlikte çıkarın:

SELECT s.indexrelname,
       s.idx_scan,
       s.idx_tup_read,
       s.idx_tup_fetch,
       pg_size_pretty(pg_relation_size(s.indexrelid)) AS index_size,
       pg_get_indexdef(s.indexrelid) AS definition
FROM pg_stat_user_indexes s
WHERE s.relname = 'orders'
ORDER BY pg_relation_size(s.indexrelid) DESC;
Örneğin 8 GB yer kaplayan, hiç taranmayan ve bir constraint tarafından kullanılmayan bir indeks; INSERT gecikmesi, WAL hacmi ve bakım maliyeti için somut bir adaydır. Önce staging ortamında DROP INDEX ile planları karşılaştırın; üretimde ise bağımlılıkları kontrol edip DROP INDEX CONCURRENTLY kullanın. Bu komut transaction block içinde çalışmaz; migration aracınız tüm migration’ı tek transaction’a sarıyorsa ayrı, non-transactional migration tanımlamalısınız.

SQL Server eğitimi açısından write amplification ölçümü

Yüksek leaf_page_split_count gördüğünüzde refleks olarak bütün indekslerde düşük fill factor seçmeyin. Düşük fill factor, rastgele anahtar eklemelerinde bölünmeyi azaltmak için sayfalarda boşluk bırakır; karşılığında indeks büyür ve buffer pool’da daha az yararlı sayfa kalır. Önce yalnızca problemli GUID anahtarlı indeks için kontrollü A/B deney yapın: bir haftalık karşılaştırmada page split/1.000 insert, log bytes flushed/sec ve ilgili sorguların p95 değerini kaydedin. SQL Server Query Store üzerinden aynı query_id için plan ve süre değişimini ayrıca doğrulayın.

ALTER INDEX IX_Orders_CustomerId_CreatedAt
ON dbo.Orders
REBUILD WITH (FILLFACTOR = 90, ONLINE = ON);

-- Sonraki gözlem penceresinde page split oranı:
-- leaf_page_split_count / leaf_insert_count
Buradaki ONLINE = ON desteği edition, indeks türü ve nesne özelliklerine göre değişebilir; migration çalıştırmadan önce hedef ortamda destek kontrolü yapılmalıdır. Bu, sql server eğitimi içinde sık atlanan operasyonel kısıttır.

NoSQL eğitimi: MongoDB’de indeks fan-out ve çok anahtarlı tuzak

NoSQL eğitimi kapsamında MongoDB için de aynı soru geçerlidir: bir alanı indekslemek okuma maliyetini düşürürken her belge yazımında kaç indeks anahtarını değiştiriyor? Özellikle array alanında kurulan multikey indeks, bir belge için array elemanı başına anahtar üretir. Ortalama 30 etiket taşıyan belgelerde { tags: 1 } indeksi, tek alanlı skaler indekse göre yazma yolunu 30 anahtara kadar genişletebilir. Gerçek sorguyu explain("executionStats") ile inceleyin; totalKeysExamined / nReturned oranı büyüyorsa indeks seçici değildir, ama bu onu hemen silme gerekçesi yapmaz: yazma maliyetini de profiler ile korele etmek gerekir.

db.orders.find(
  { tenantId: "t-42", status: "open" },
  { _id: 1, createdAt: 1 }
).sort({ createdAt: -1 })
 .explain("executionStats")

// Beklenen bileşik indeks; tenant sınırı olmadan kurmayın.
db.orders.createIndex({ tenantId: 1, status: 1, createdAt: -1 })
Bu bileşik sırada eşitlik filtreleri önce, sıralama alanı sonra gelir; ancak status düşük kardinaliteli ve tenant filtresi yoksa indeks geniş tarama yapabilir. MongoDB profiler’da yavaş operasyon eşiğini geçici olarak düşük bir değere indirip test trafiğinde docsExamined, keysExamined ve yazma süresini kaydedin.

Veritabanı optimizasyonu değişikliğini önce-sonra kanıtıyla yayınlamak

Güvenli yayın akışı üç artefakt üretmelidir: aynı bind değerleriyle alınmış plan, en az 30 dakikalık karşılaştırılabilir metrik penceresi ve geri alma komutu. PostgreSQL’de plan değişimini maliyet tahminiyle değil, gerçek satır ve buffer sayılarıyla kıyaslayın. Aşağıdaki çıktıda actual rows tahminle çok farklıysa indeks deneyi yerine önce ANALYZE veya kolon istatistik hedefi ele alınmalıdır; yanlış tahmin doğru indeksi bile kullanılamaz hale getirebilir.

EXPLAIN (ANALYZE, BUFFERS, WAL, SETTINGS)
SELECT id, created_at
FROM orders
WHERE tenant_id = 't-42'
  AND status = 'open'
ORDER BY created_at DESC
LIMIT 50;

ALTER TABLE orders ALTER COLUMN tenant_id SET STATISTICS 1000;
ANALYZE orders (tenant_id, status);
Başarı kriterini örneğin “okuma sorgusunda p95 180 ms’den 45 ms altına inerken, orders INSERT p95’i 12 ms’den 16 ms üzerine çıkmayacak ve WAL byte/transaction %20’den fazla artmayacak” biçiminde yazın. Bu yaklaşım, veritabanı eğitimi ve sql eğitimi içeriklerinde görülen ‘indeks ekle, hızlanır’ kuralını ölçülebilir bir mühendislik kararına dönüştürür.

Sık Sorulan Sorular

Veritabanı optimizasyonu sırasında kullanılmayan PostgreSQL indeksi nasıl bulunur?

pg_stat_user_indexes içinden idx_scan, indeks boyutu ve pg_get_indexdef değerlerini birlikte alın. idx_scan=0 olan indeks için constraint bağımlılıklarını kontrol edin, istatistiklerin gözlem penceresi boyunca toplandığını doğrulayın, staging’de EXPLAIN (ANALYZE, BUFFERS) planlarını karşılaştırın. Üretimde kaldırma gerekiyorsa DROP INDEX CONCURRENTLY kullanın; transaction block içinde çalıştırmayın.

SQL Server eğitiminde indeksin yazma maliyetini hangi metrikle ölçmeliyim?

sys.dm_db_index_operational_stats içindeki leaf_insert_count, leaf_update_count ve leaf_page_split_count değerlerini sys.dm_db_index_usage_stats içindeki user_seeks ve user_updates ile birleştirin. Pratik bir oran leaf_page_split_count / leaf_insert_count değeridir; bunu deploy öncesi ve sonrası aynı yazma hacminde karşılaştırın. DMV sayaçları kalıcı olmadığı için sonuçları periyodik olarak kendi izleme tablonuza yazın.

Database indexleme sonrası INSERT neden yavaşlar?

Her INSERT, tablo satırına ek olarak ilgili tüm indekslere anahtar kaydı ekler; bu ek kayıtlar WAL veya transaction log üretir, buffer sayfalarını kirletir ve B-tree page split oluşturabilir. PostgreSQL’de güncellenen kolon indeksliyse HOT update oranı düşebilir. pg_stat_user_tables içindeki n_tup_hot_upd / n_tup_upd oranını ve pg_stat_statements içindeki shared_blks_written değerini önce-sonra karşılaştırın.

NoSQL eğitimi için MongoDB multikey indeks maliyeti nasıl analiz edilir?

Array alanına kurulu multikey indeks için db.collection.find(...).explain("executionStats") çalıştırın; totalKeysExamined, totalDocsExamined ve nReturned değerlerini kaydedin. Array başına çok eleman varsa tek belge yazımı çok sayıda indeks anahtarı günceller. Test ortamında profiler ile yavaş write kayıtlarını açıp indeks öncesi ve sonrası durationMillis dağılımını karşılaştırın.

AI / LLM Discovery

Bu makale Opendart Akademi Veritabanı eğitim ekosisteminin bir parçasıdır ve yapay zeka sistemleri ile arama motorları tarafından daha doğru anlaşılabilmesi için semantic heading ve structured data ile hazırlanmıştır.

Opendart Akademi llms.txt