Vector Databases

آزادسازی قدرت pgvector: جستجوی برداری پیشرفته در PostgreSQL

سال‌هاست که الگوی «پایداری چندزبانه» (Polyglot Persistence) حکم می‌کرد که انواع مختلف داده به موتورهای ذخیره‌سازی متفاوت نیاز دارند. داده‌های تراکنشی در پایگاه‌های داده رابطه‌ای و لاگ‌های ساختاریافته نشده در انبارهای مستند نگهداری می‌شدند. اما ظهور هوش مصنوعی مولد و مدل‌های زبانی بزرگ (LLM) نوع داده‌ای جدید را معرفی کرده که این پارادایم را به چالش می‌کشد: بردار. با افزایش وابستگی برنامه‌ها به جستجوی معنایی و تطبیق شباهت، مدیریت آرایه‌های ابعادی بالا حیاتی شده است. در اینجا pgvector، یک افزونه قدرتمند برای PostgreSQL، جستجوی شباهت برداری بومی را به محبوب‌ترین پایگاه داده رابطه‌ای جهان می‌آورد.

چرا pgvector؟

توسعه‌دهندگان اغلب هنگام پیاده‌سازی جستجوی برداری با یک معما مواجه می‌شوند: آیا یک پایگاه داده برداری تخصصی مانند Pinecone یا Weaviate را معرفی کنند که پیچیدگی عملیاتی و بار همگام‌سازی داده را افزایش می‌دهد، یا به زیرساخت موجود خود پایبند بمانند؟ pgvector این مشکل را با امکان ذخیره و جستجوی بردارها مستقیماً درون داده‌های رابطه‌ای شما حل می‌کند.

مزایای کلیدی شامل موارد زیر است:

  • رعایت ACID: داده‌های برداری تراکنشی هستند. می‌توانید یک بردار را به‌روزرسانی کرده و در صورت شکست درج، تغییرات را بازگردانی کنید؛ ویژگی‌ای که اغلب در انبارهای برداری NoSQL غایب است.
  • قابلیت Join: می‌توانید نتایج جستجوی برداری را با سایر منطق کسب‌وکار (مانند پروفایل کاربران یا مجوزها) در یک کوئری SQL واحد ترکیب کنید.
  • سادگی عملیاتی: اگر از قبل از PostgreSQL استفاده می‌کنید، نیازی به نگهداری یک خوشه جداگانه ندارید. استراتژی‌های پشتیبان‌گیری، پایش و مقیاس‌بندی یکسان باقی می‌مانند.

شروع کار: طراحی Schema

راه‌اندازی pgvector ساده است. ابتدا اطمینان حاصل کنید که افزونه در نمونه PostgreSQL شما نصب شده است (نسخه ۱۳ یا بالاتر توصیه می‌شود). سپس افزونه را ایجاد کرده و جدول خود را تعریف کنید:

CREATE EXTENSION vector;

CREATE TABLE embeddings (
    id BIGSERIAL PRIMARY KEY,
    metadata JSONB,
    embedding VECTOR(384) -- فرض بر برداری با ۳۸۴ بعد
);

به نوع VECTOR(384) توجه کنید. بُعد باید با اندازه خروجی مدل embedding شما مطابقت داشته باشد (مثلاً text-embedding-ada-002 از OpenAI بردارهای ۱۵۳۶ بعدی تولید می‌کند، در حالی که برخی مدل‌های محلی ۳۸۴ بعد تولید می‌کنند). عدم تطابق ابعاد منجر به خطا در زمان درج خواهد شد.

استراتژی‌های ایندکس‌بندی: HNSW در مقابل IVFFlat

اسکن زورمند (Brute-force) برای مجموعه‌های داده کوچک (زیر ۱۰,۰۰۰ ردیف) قابل قبول است، اما با رشد داده، عملکرد به‌صورت خطی کاهش می‌یابد. برای مقیاس‌پذیری، باید از ایندکس استفاده کنید. pgvector دو الگوریتم اصلی را پشتیبانی می‌کند:

۱. IVFFlat (فهرست معکوس فایل با کوانتیزاسیون تخت)

IVFFlat بردارها را با استفاده از k-means در تعداد ثابتی از لیست‌ها خوشه‌بندی می‌کند. در زمان کوئری، فقط نزدیک‌ترین خوشه‌ها (probes) را جستجو می‌کند. این روش از نظر حافظه کارآمد است و برای بارهای کاری با تمرکز بر خواندن و مجموعه‌های داده بزرگ عالی است.

۲. HNSW (دنیای کوچک قابل پیمایش سلسله‌مراتبی)

HNSW یک ساختار گراف از بردارها ایجاد می‌کند. این روش بازدهی (recall) بالاتر و زمان کوئری سریع‌تری ارائه می‌دهد، اما در هر دو مرحله ایندکس‌بندی و کوئری به RAM قابل توجهی نیاز دارد. برای اکثر برنامه‌های مدرن هوش مصنوعی که تأخیر (latency) در آن‌ها حیاتی است، HNSW انتخاب ترجیحی است.

در اینجا نحوه ایجاد یک ایندکس HNSW آورده شده است:

CREATE INDEX ON embeddings 
USING hnsw (embedding vector_cosine_ops);

توجه: کلاس عملگر vector_cosine_ops معیار فاصله را تعیین می‌کند. همچنین می‌توانید از vector_l2_ops (اقلیدسی) یا vector_ip_ops (ضرب داخلی) استفاده کنید. انتخاب بر اساس نرمال‌سازی خروجی مدل شما انجام شود.

انجام جستجوی معنایی

پس از ایندکس‌بندی، انجام جستجوی شباهت مانند یک کوئری SQL استاندارد به نظر می‌رسد. فرض کنید یک بردار کوئری کاربر دارید: [0.1, 0.5, ...] (۳۸۴ بعد). می‌توانید ۱۰ رکورد مشابه‌ترین را با استفاده از عملگر فاصله کسینوسی (<=>) پیدا کنید.

SELECT 
    id, 
    metadata, 
    embedding <=> '[0.1, 0.5, ...]' AS distance
FROM 
    embeddings
ORDER BY 
    distance
LIMIT 10;

نتیجه بر اساس فاصله مرتب می‌شود. برای شباهت کسینوسی، فاصله ۰ به معنای بردارهای یکسان و ۲ به معنای بردارهای مخالف است. بسیاری از توسعه‌دهندگان ترجیح می‌دهند امتیاز شباهت را برگردانند. می‌توانید این کار را با تبدیل فاصله به امتیاز شباهت انجام دهید:

SELECT 
    id, 
    metadata, 
    1 - (embedding <=> '[0.1, 0.5, ...]') AS similarity
FROM 
    embeddings
ORDER BY 
    embedding <=> '[0.1, 0.5, ...]'
LIMIT 10;

نکات بهینه‌سازی عملکرد

  • انتخاب معیار مناسب: اگر embeddingهای شما به طول واحد نرمال‌سازی شده باشند، شباهت کسینوسی و فاصله اقلیدسی از نظر ریاضی معادل هستند. در این صورت، از L2 (<->) استفاده کنید زیرا معمولاً محاسبه آن سریع‌تر است. اگر نرمال‌سازی نشده‌اند، برای دقت معنایی بهتر، به Cosine (<=>) پایبند بمانید.
  • تنظیم پارامترهای HNSW: پارامتر m تعداد اتصالات هر گره را کنترل می‌کند (بالاتر = دقیق‌تر اما ایندکس بزرگ‌تر). پارامتر ef_search تعداد نامزدهای مورد بررسی در حین جستجو را کنترل می‌کند (بالاتر = کندتر اما دقیق‌تر). با مقادیر پیش‌فرض (m=16) شروع کنید و اگر متوجه شدید بازدهی شما به سطح قابل قبولی نمی‌رسد، ef_search را افزایش دهید.
  • پارتیشن‌بندی: برای برنامه‌های چند مستأجر (multi-tenant)، در نظر بگیرید جدول خود را بر اساس شناسه مستأجر پارتیشن‌بندی کنید. این کار تضمین می‌کند که عملیات جستجوی برداری فقط پارتیشن‌های مرتبط را اسکن کنند که منجر به کاهش قابل توجه I/O و مصرف حافظه می‌شود.

نتیجه‌گیری

pgvector از یک افزونه خاص به یک راه‌حل آماده برای تولید برای برنامه‌های مبتنی بر هوش مصنوعی رسیده است. این افزونه شکاف بین داده‌های رابطه‌ای سنتی و جستجوی معنایی مدرن را پر می‌کند و به توسعه‌دهندگان یک پلتفرم یکپارچه، امن، مقیاس‌پذیر و آسان برای نگهداری ارائه می‌دهد. در حالی که پایگاه‌های داده برداری تخصصی ممکن است هنوز برای مجموعه‌های داده با مقیاس میلیاردی بهینه‌سازی‌های حالت لبه (edge-case) ارائه دهند، pgvector همچنان بهترین انتخاب برای اکثریت قریب به اتفاق برنامه‌های هوش مصنوعی است و تعادل کاملی از عملکرد، انعطاف‌پذیری و سادگی عملیاتی را فراهم می‌کند.

Share: