PostgreSQL'de Hibrit Arama Mimarisi: Full-Text Search ve pgvector Entegrasyonu
Arama motoru teknolojileri son birkaç yılda radikal bir değişim geçirdi. Artık kullanıcılar sadece "kelime eşleşmesi" değil, "niyet eşleşmesi" bekliyor. PostgreSQL, geleneksel Full-Text Search (FTS) yeteneklerini pgvector eklentisiyle birleştirerek, harici bir vektör veritabanına ihtiyaç duymadan "Hibrit Arama" (Hybrid Search) yapabilmenize olanak tanıyor.
1. Full-Text Search (FTS) Mekanizması
PostgreSQL FTS, metinleri dilsel bir analize tabi tutar. Bu süreçte kelimeler köklerine ayrılır (stemming) ve "ve, veya, ile" gibi anlamsız kelimeler (stop words) temizlenir. Sonuçta ortaya çıkan tsvector verisi, hızlı erişim için GIN (Generalized Inverted Index) ile indekslenir.
Teknik Derinlik: Sözlükler ve Ağırlıklandırma
FTS'te başlık (Title) ve içerik (Body) kısımlarına farklı ağırlıklar vererek arama kalitesini artırabilirsiniz (Örn: Başlıkta geçen kelime 4 kat daha değerli olsun):
-- Ağırlıklı tsvector oluşturma
SELECT setweight(to_tsvector('turkish', coalesce(title,'')), 'A') ||
setweight(to_tsvector('turkish', coalesce(content,'')), 'B')
AS weighted_vector;
2. pgvector ile Semantik Arama
Vektör arama, kelimeleri veya cümleleri OpenAI (text-embedding-3) veya HuggingFace modelleriyle sayısal koordinatlara dönüştürür. pgvector bu vektörleri saklar ve aralarındaki "mesafeyi" ölçer.
HNSW İndeksi: Hızın Anahtarı
Milyonlarca satırlık vektör verisinde arama yapmak CPU yoğundur. HNSW (Hierarchical Navigable Small World) indeksi, verileri katmanlı bir grafik yapısında tutarak, milisaniyeler içinde en yakın sonuçları bulmanızı sağlar.
// C# / EF Core ile pgvector mesafe sorgusu
var vector = new Vector(new float[] { 0.12f, 0.45f, ... });
var items = await _context.Products
.OrderBy(p => p.Embedding.L2Distance(vector)) // Öklid mesafesi
.Take(10)
.ToListAsync();
3. Hibrit Mimari: RRF (Reciprocal Rank Fusion)
Neden her ikisi? Çünkü FTS; "iPhone 15 Pro" gibi spesifik modellerde kusursuzdur. Vektör arama ise "gece fotoğrafçılığı için en iyi telefon" gibi konseptlerde başarılıdır. Bu iki skoru birleştirmek için RRF algoritması kullanılır:
-- Hibrit Arama (SQL)
WITH fts_results AS (
SELECT id, row_number() OVER (ORDER BY ts_rank(content_vector, query) DESC) as rank
FROM products, to_tsquery('turkish', 'akıllı & telefon') query
WHERE content_vector @@ query
LIMIT 50
),
vector_results AS (
SELECT id, row_number() OVER (ORDER BY embedding <=> '[0.1, 0.2...]'::vector) as rank
FROM products
ORDER BY embedding <=> '[0.1, 0.2...]'::vector
LIMIT 50
)
SELECT p.title,
(1.0 / (60 + f.rank) + 1.0 / (60 + v.rank)) as combined_score
FROM products p
JOIN fts_results f ON p.id = f.id
JOIN vector_results v ON p.id = v.id
ORDER BY combined_score DESC;
Performans ve Ölçeklenebilirlik Önerileri
- RAM Yönetimi: HNSW indeksleri bellekte tutulur. Veritabanı RAM miktarınızın indeks boyutundan büyük olduğundan emin olun.
- Batch Embedding: Verileri güncellerken tek tek değil, toplu (batch) olarak embedding oluşturun.
- PostgreSQL 16+: Paralel sorgu işleme yetenekleri için güncel versiyonları tercih edin.
Sonuç
PostgreSQL ile hibrit arama kurmak, veri tutarlılığını tek noktada toplamanızı sağlar. Farklı bir arama motoru servisinin maliyeti ve senkronizasyon karmaşasından kurtulurken, kullanıcılarınıza Google kalitesinde arama deneyimi sunabilirsiniz.