
HNSW vs IVFFlat: pgvector İndeksleme Stratejisinde Sorgu Gecikmesi ve Bellek Tüketimi Dengesi

Giriş
Vektör veritabanlarını production ortamında ölçeklendirirken, mimari ekiplerin karşılaştığı en kritik dar boğaz, indeksleme stratejisinin seçimidir. 1536 boyutlu (örneğin OpenAI text-embedding-ada-002) 5 milyon kayıttan oluşan bir veri setinde tam k-NN (Exact K-Nearest Neighbors) araması yapmak, Seq Scan (Sequential Scan) ile saniyeler süren gecikmelere yol açar. Bu noktada Approximate Nearest Neighbor (ANN) algoritmaları devreye girer. Ancak PostgreSQL’in pgvector eklentisi üzerinde hangi ANN algoritmasının kullanılacağı (HNSW mi, IVFFlat mi?) rastgele alınabilecek bir karar değildir.
2023’ün üçüncü çeyreğinde, saniyede 500 sorgu (500 QPS) alan bir semantik arama servisini ölçeklendirirken bu kararın altyapı maliyetlerine ve sistem stabilitesine olan etkilerini birinci elden test etme fırsatım oldu. Yanlış konfigüre edilmiş bir IVFFlat indeksi recall (doğruluk) oranını %65’lere kadar düşürebilirken, varsayılan ayarlarla bırakılmış bir HNSW indeksi, 16 GB RAM’e sahip bir veritabanı sunucusunu OOM (Out of Memory) hatası ile çökertebilir. Bu metin, pgvector üzerinde vektör indeksleme stratejisi kurgularken, donanım kaynakları ile sorgu gereksinimleri arasındaki trade-off (ödünleşim) üçgenini (Gecikme – Doğruluk – Bellek) matematiksel ve pratik düzeyde incelemektedir.
İçindekiler
- pgvector İndeksleme Anatomisi
- IVFFlat (Inverted File with Flat Compression) Analizi
- HNSW (Hierarchical Navigable Small World) Analizi
- Karşılaştırma Tablosu: HNSW vs IVFFlat
- Production Vakası: 5 Milyon Vektörlük RAG Altyapısı
- Hangi Senaryoda Hangisi Seçilmeli?
- Pratik Öneriler / Production Notları
- Sık Sorulan Sorular
- Sonuç
pgvector İndeksleme Anatomisi
PostgreSQL ekosisteminde metin tabanlı aramalar için B-Tree veya GIN ne kadar standartsa, yüksek boyutlu kayan nokta (floating-point) dizileri için de ANN indeksleri o derece kritiktir. pgvector eklentisi, 0.5.0 sürümüne kadar yalnızca IVFFlat desteklerken, bu sürümle birlikte HNSW (Hierarchical Navigable Small World) yapısını da kullanıma sundu. İki indeks türü de L2 uzaklığı (<->), İç Çarpım / Inner Product (<#>) ve Kosinüs Uzaklığı / Cosine Distance (<=>) metrikleriyle çalışır. Ancak indekslerin diske yazılma biçimleri, RAM üzerinde kapladıkları alan ve CPU döngülerini kullanma şekilleri birbirlerinden tamamen farklıdır.
IVFFlat (Inverted File with Flat Compression) Analizi
Çalışma Prensibi ve Matematiksel Arka Plan
IVFFlat, vektör uzayını K-Means kümeleme (clustering) algoritması kullanarak belirli sayıda alt bölgeye (Voronoi hücrelerine) ayırır. İndeks oluşturma aşamasında veritabanındaki mevcut kayıtlar taranır, küme merkezleri (centroids) hesaplanır ve her vektör kendisine en yakın küme merkezine ait olan ters çevrilmiş bir listeye (inverted list) eklenir. Sorgu anında ise hedef vektöre en yakın N adet küme merkezi bulunur ve sadece bu kümelerin içindeki vektörler taranarak L2 veya Cosine hesaplaması yapılır.
Bu mekanizmanın en büyük dezavantajı, indeksin veri dağılımına bağımlı olmasıdır. Eğer tablo boşken IVFFlat indeksi oluşturursanız, K-Means algoritması küme merkezlerini hesaplayamaz ve sistem tüm sorgularda Seq Scan yapar. Veri dağılımı zamanla değiştikçe, orijinal küme merkezleri geçerliliğini yitirir ve recall oranı düşer. Bu senaryoda indeksin REINDEX ile yeniden oluşturulması şarttır.
Bellek ve CPU Profili
IVFFlat’in en büyük avantajı, bellek tüketimindeki muazzam tasarrufudur. 1536 boyutlu 1 milyon vektör, diskte yaklaşık 6 GB yer kaplar. Bu veri seti üzerinde oluşturulan bir IVFFlat indeksinin boyutu ise genellikle 100-150 MB civarındadır. İndeks, temel olarak sadece küme merkezlerinin koordinatlarını ve bu kümelere ait kayıtların işaretçilerini (pointer) tutar. CPU tarafında indeks oluşturma süreci (K-Means nedeniyle) işlem yoğun olsa da, RAM tarafında operasyonel maliyeti asgari düzeydedir.
Optimizasyon ve Parametreler
IVFFlat kullanırken ayarlanması gereken iki temel parametre vardır:
- lists: İndeks oluşturulurken tanımlanan küme sayısıdır. 1 milyon altındaki kayıtlar için
satır_sayısı / 1000, 1 milyon üstündeki kayıtlar içinsqrt(satır_sayısı)formülü optimum sonuç verir. - probes: Sorgu sırasında kaç kümenin taranacağını belirler.
listsdeğerinin %10’u ile başlamak iyi bir referans noktasıdır. Sayı arttıkça recall yükselir, ancak gecikme de artar.
-- Tabloda yeterli veri olduğundan emin olduktan sonra indeks oluşturma
CREATE INDEX idx_documents_ivfflat ON documents
USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 1000);
-- Sorgu anında session bazlı probe ayarı
SET ivfflat.probes = 100;
SELECT id, content, 1 - (embedding <=> '[0.1, 0.2, ...]') AS similarity
FROM documents
ORDER BY embedding <=> '[0.1, 0.2, ...]'
LIMIT 5;
HNSW (Hierarchical Navigable Small World) Analizi
Çalışma Prensibi
HNSW, Skip-List ve Delaunay üçgenlemesi kavramlarını birleştiren, çok katmanlı bir graf yapısıdır. Vektörler, farklı yoğunluklara sahip katmanlar halinde organize edilir. En üst katmanlarda çok az sayıda vektör ve uzun mesafeli bağlantılar (edge) bulunurken, alt katmanlara inildikçe vektör yoğunluğu artar. Sorgu işlemi en üst katmandan başlar, yerel bir minimum bulunana kadar ilerler ve ardından bir alt katmana inerek süreci tekrarlar (Greedy Search).
IVFFlat’in aksine, HNSW veri dağılımına baştan ihtiyaç duymaz. Tablo boşken indeks oluşturulabilir ve yeni eklenen kayıtlar graf yapısına dinamik olarak entegre edilir. Bu yapısal esneklik, sık veri eklenen veya güncellenen (high-write) RAG sistemleri için HNSW’yi cazip kılar.
Bellek Tüketimi Karakteristiği
HNSW’nin en belirgin handikabı RAM ve disk kullanımıdır. Her vektör için birden fazla bağlantı (pointer) saklanması gerektiğinden, indeks boyutu veri setinin kendisine yaklaşabilir veya onu geçebilir. HNSW indeks boyutunu kabaca hesaplamak için: (m * 4 byte + 8 byte) * katman_sayısı * vektör_sayısı temel alınabilir. 1 milyon vektörlük bir set için HNSW indeksi rahatlıkla 2-3 GB RAM alanı talep edebilir.
HNSW ayarlarında iki kritik parametre bulunur:
- m: Graf üzerindeki her bir düğümün (vektörün) sahip olacağı maksimum çift yönlü bağlantı sayısı. 16 ile 64 arası değerler yaygındır. Yüksek
mdeğeri, recall oranını artırırken RAM tüketimini katlar. - ef_construction: İndeks oluşturma (veya insert) sırasında incelenecek adayların havuz büyüklüğü. Yüksek değerler (örn: 128 veya 256), çok daha kaliteli bir graf yapısı oluşturur ancak insert (yazma) gecikmesini ciddi oranda artırır.
-- HNSW indeksi oluşturma (M ve ef_construction optimizasyonu ile)
CREATE INDEX idx_documents_hnsw ON documents
USING hnsw (embedding vector_cosine_ops)
WITH (m = 24, ef_construction = 128);
-- Sorgu anında dinamik aday havuzu büyüklüğü
SET hnsw.ef_search = 100;
SELECT id, content FROM documents
ORDER BY embedding <=> '[0.1, 0.2, ...]'
LIMIT 5;
Karşılaştırma Tablosu: HNSW vs IVFFlat
| Metrik / Özellik | IVFFlat | HNSW |
|---|---|---|
| Sorgu Gecikmesi (p99) | Orta (~120ms – 300ms) | Çok Düşük (~20ms – 50ms) |
| Recall (Doğruluk) Oranı | %75 – %85 (Veri değiştikçe düşer) | %95 – %99 (İstikrarlı) |
| RAM ve Disk Maliyeti | Düşük (~%2-5 ek yük) | Çok Yüksek (~%30-50 ek yük) |
| İndeks Oluşturma Süresi | Düşük | Yüksek (Özellikle büyük ef_construction) |
| Incremental Insert Desteği | Kötü (Sık REINDEX gerektirir) |
Mükemmel (Graf dinamik güncellenir) |
| Cold Start (Boş Tablo) | Desteklemez | Destekler |
Production Vakası: 5 Milyon Vektörlük RAG Altyapısı
Geçtiğimiz yıl, kurumsal dokümanların arandığı bir RAG uygulamasında 5.2 milyon vektörlük bir tabloya (1536 boyutlu vektörler, tablonun fiziksel boyutu yaklaşık 32 GB) sahip bir PostgreSQL cluster’ını optimize ettik. Başlangıçta sistemde IVFFlat (lists = 2200) kurgulanmıştı. Günlük 150.000 yeni vektörün sisteme insert edilmesi nedeniyle, her 10 günde bir recall oranı %82 seviyelerinden %68’e kadar geriliyordu. Ayrıca sistem yoğun kullanım altındayken probes=150 ayarı kullanıldığında p99 gecikmesi 420ms bandına çıkıyordu.
Sunucuda 64 GB RAM bulunuyordu ve paylaşımlı tamponlar (shared_buffers) 16 GB olarak ayarlanmıştı. Ekibin kararıyla HNSW geçişi planlandı. Geçiş stratejisi aşağıdaki adımlarla uygulandı:
- Mevcut tabloda yazma (write) kilitlerini engellemek için
CREATE INDEX CONCURRENTLYkullanıldı. m=16veef_construction=64değerleri seçildi. Bu değerler, %97 recall oranını garanti altına alan ancak RAM maliyetini sınırlayan optimum noktalardı.maintenance_work_memgeçici olarak 8GB’a çıkarıldı ve indeksin inşası yaklaşık 45 dakika sürdü.
Sonuçlar: Geçişin ardından p99 gecikmesi 420ms’den 38ms’ye geriledi. Günlük veri eklemelerine rağmen recall oranı %97-98 bandında sabit kaldı. Ancak, HNSW indeksinin diskteki boyutu 4.8 GB oldu (IVFFlat sadece 140 MB’dı). Sunucunun RAM kapasitesi yeterli olduğu için bu ek maliyet tolere edilebildi, ancak 16 GB RAM’e sahip daha küçük bir staging ortamı, indeks oluşturma sırasında OOM (Out of Memory) hatası verdi ve max_parallel_maintenance_workers parametresinin düşürülmesi gerekti.
Hangi Senaryoda Hangisi Seçilmeli?
HNSW Seçmeniz Gereken Durumlar
- Gecikme Toleransı Yoksa: Kullanıcıya anında yanıt dönmesi gereken chatbot veya gerçek zamanlı arama sistemlerinde (p99 < 50ms hedefi).
- Sürekli Veri Akışı Varsa (High Churn): Veri setinin %10’undan fazlası haftalık olarak değişiyor, siliniyor veya güncelleniyorsa. HNSW graf yapısı bu değişimleri tolere edebilir.
- Donanım Kısıtlaması Yoksa: İndeksi bütünüyle RAM’de tutabilecek (veya işletim sistemi sayfa önbelleğine, OS Page Cache, sığdırabilecek) yüksek kapasiteli sunucularınız varsa.
- Recall Kritikse: Medikal araştırmalar veya hukuki belge taramaları gibi, ilgili sonuçların %95 ve üzerinde eksiksiz getirilmesinin zorunlu olduğu projeler.
IVFFlat Seçmeniz Gereken Durumlar
- Donanım (RAM) Sınırlıysa: Edge computing cihazlarında, düşük maliyetli sanal makinelerde veya RAM’in başka yoğun sorgular tarafından paylaşıldığı sistemlerde.
- Veri Seti Statikse: Vikipedi arşivi veya sabit bir ürün kataloğu gibi verilerin eklendikten sonra nadiren değiştiği senaryolarda.
- Milyarlarca Kayıt Varsa: 100 milyon veya 1 milyar vektörlük bir setiniz varsa, HNSW’nin bellek maliyeti terabaytlar seviyesine ulaşır. Bu devasa ölçeklerde IVFFlat (hatta bazen kuantizasyon teknikleriyle birleştirilerek) tek donanımsal çıkış yoludur.
- Kabul Edilebilir Recall Yeterliyse: %80-85 arası doğruluk oranının son kullanıcı deneyimini bozmadığı tavsiye sistemleri.
Pratik Öneriler / Production Notları
Vektör indekslerinin tam performansı, ancak indeks verisi tamamen bellekte (RAM) olduğunda ortaya çıkar. Disk okumaları (I/O) ANN algoritmalarının doğasını bozarak sorgu sürelerini yüzlerce milisaniyeye çıkarır.
- İndeks Isıtma (Pre-warming): Veritabanı yeniden başlatıldığında, HNSW indeksinin ilk sorgularda yavaş yanıt vermesini engellemek için
pg_prewarmeklentisini kullanarak indeksi paylaşımlı tamponlara (shared buffers) zorlayın.SELECT pg_prewarm('idx_documents_hnsw'); - Kısmi İndeksler (Partial Indexes): Vektör tablolarınızda ‘tenant_id’ veya ‘is_active’ gibi filtreler kullanıyorsanız, genel bir indeks yerine kısmi indeksler oluşturun. Bu hem RAM tüketimini radikal şekilde düşürür hem de arama uzayını daraltır.
CREATE INDEX idx_active_docs_hnsw ON documents USING hnsw (embedding vector_cosine_ops) WHERE is_active = true; - İşlemci Mimarisi ve Optimizasyon:
pgvectorderlenirken, sunucunun işlemci komut setlerinden (AVX-512, f16c) faydalanması çok kritiktir. Postgres container’ı kullanıyorsanız, donanım optimizasyonlu imajları seçtiğinizden emin olun. Bu, L2 ve Cosine mesafe hesaplama sürelerinde %40’a varan düşüş sağlar. - Sorgu Planı İncelemesi:
EXPLAIN ANALYZEile sorgularınızı kontrol edin. EğerIndex ScanyerineSeq Scangörüyorsanız; veri setinizdeki boyut sayısı (örn: 1536) ile indeksteki operatör sınıfı uyuşmuyor olabilir veya sorguda kullandığınız mesafe operatörü (<=>) indeksin derlendiği operatörle (vector_cosine_ops) aynı değildir.
Sık Sorulan Sorular
1. Tablomda 50.000 kayıt var, HNSW mi kurmalıyım?
50.000 kayıt, vektör uzayı için mikro ölçekli bir veridir. Eğer 1536 boyut kullanıyorsanız, 50 bin kayıt yaklaşık 300 MB yer kaplar. Seq Scan bile 10-15ms civarında yanıt verebilir. Ancak p99 gecikmesini 2-3ms seviyesine çekmek istiyorsanız, HNSW (küçük bir m=8 değeri ile) kurabilirsiniz.
2. IVFFlat ne sıklıkla yeniden indekslenmeli (REINDEX)?
Veri setinizin hacmi %20 oranında değiştiğinde (yeni insert’ler veya update’ler sebebiyle), orijinal K-Means küme merkezleri geçerliliğini kaybetmeye başlar. Sisteminize bağlı olarak, bir cron job yardımıyla haftalık veya aylık olarak trafiğin en düşük olduğu saatlerde REINDEX INDEX CONCURRENTLY idx_name; çalıştırmanız recall oranını eski seviyesine getirecektir.
3. ef_search parametresini artırmak gecikmeyi nasıl etkiler?
ef_search değeri, HNSW indeksinde sorgu anında taranacak aday havuzunu belirler. Değeri 10’dan 100’e çıkarmak, p99 gecikmesini yaklaşık 3-4 kat artırabilir (örneğin 12ms’den 45ms’ye) ancak recall oranını %90’lardan %99’lara taşır. Bu değeri session bazında (sorgudan hemen önce) uygulamanın ihtiyacına göre dinamik olarak ayarlayabilirsiniz.
4. Operatör seçiminin (L2 vs Cosine) performansa etkisi var mı?
İşlemci seviyesinde L2 (Öklid) mesafesi hesaplamak, Kosinüs mesafesi hesaplamaktan bir miktar daha az maliyetlidir. Ancak OpenAI gibi normalize edilmiş embedding modelleri kullanıyorsanız, iç çarpım (Inner Product <#>) operatörünü kullanmak matematiksel olarak Cosine ile aynı sonucu verecek ve donanım tarafında işlemci döngülerini daha efektif (cache hit oranını artırarak) kullanacaktır.
Sonuç
Vektör tabanlı yapay zeka uygulamalarında pgvector kullanımı söz konusu olduğunda evrensel olarak “en iyi” tek bir indeks türü yoktur. HNSW, sağladığı düşük p99 gecikmesi ve veri değişimlerine karşı gösterdiği yapısal direnç ile özellikle donanım kaynağının bol olduğu senaryolarda birinci öncelik olmalıdır. Veri setiniz büyüdükçe RAM tüketimi doğrusal olarak fırlayacağı için altyapı monitörlerinizde bellek uyarısı tanımlamanız şarttır.
Öte yandan IVFFlat, donanım kaynaklarının (özellikle RAM) kısıtlı olduğu, verinin statik doğada kaldığı veya multi-milyar boyutlarına ulaşan arşive yönelik vektör tablolarında eşsiz bir maliyet avantajı sunar. Mimari kararınızı verirken; uygulamanızın gecikme hedefini, mevcut sunucu belleğinizi ve veritabanına yapılan günlük yazma oranını formüle ederek, test ortamınızda gerçek verilerinizle EXPLAIN ANALYZE kıyaslaması yapmadan production ortamına geçiş yapmamalısınız.
Bunları da beğenebilirsiniz

REST API Tasarımında Offset mi Cursor Pagination mı? Veri Büyüklüğüne Göre Karar Matrisi
Milyar satırlık tablolarda API p99 gecikmesini 1400ms’den 45ms’ye düşüren pagination stratejileri. DB execution planları ve production trade-off analizi.

Javascript veya PHP ile Lisans Anahtarı Oluşturucu
Lisans Anahtarı Oluşturma: PHP ve JavaScript ile Lisans anahtarları, yazılım ürünlerinin kopyalanmasını önlemek ve lisanslama sürecini yönetmek için kullanılan bir araçtır. Bu anahtarlar, ürünlerin yasal…

PHP ile Merkez Bankası Kurlarını Çekmek
Merhabalar, web uygulamaları geliştirirken, çeşitli finansal verilere ihtiyaç duyabiliriz. Özellikle, kullanıcılarımızın döviz kurlarına erişebilmesini sağlamak istediğimiz durumlar olabilir. Bu noktada, Merkez Bankası’nın sağladığı güncel kurları…