חיפוש וקטורי סמנטי ונושאים נוספים לזכות בחברים ובאהבות
הנוף המלא של החיפוש: מדויק, מעורפל, סמנטי, היברידי — ומתי לשלב את כולם.
החיפוש אינו דבר יחיד, והחיפוש הסמנטי אינו תחליף לשאר סוגי החיפוש.
„מצא משתמש עם המייל dan@example.com” ו‑„מצא לי מאמרים על ניפוי באגים כמהנדס חדש” מתוארים שניהם כחיפוש, אך כמעט שאין להם דבר משותף מבחינת בעיות הנדסיות. הראשון יש לו תשובה נכונה וחיפוש באינדקס ב‑O(log n). השני אין לו תשובה נכונה — רק רלוונטיות — ודורש הבנת השפה, הכוונה והמשמעות.
המהנדסים המשכנעים ביותר בהחלטות חיפוש — אלו שמנצחים בטיעונים ומשחררים את המערכת הנכונה — מבינים את כל הנוף. הם יודעים איזו כלי להשתמש ומדוע, ויכולים להסביר זאת בבירור.
מאמר זה מתמקד בשכבה הסמנטית: מה חיפוש הווקטורים עושה בפועל, מתי הוא מנצח, ואיפה הוא צריך להישאר בצד. הגרסה המועילה אינה „להטביע הכל”. היא לדעת מתי וקטורים שייכים לצד חיפוש לקסיקלי, פוזי ו‑exact‑match בארכיטקטורה היברידית.
החלק הלכסיקלי והפוזי של התמונה — tsvector, pg_trgm, pg_search — נמצא ב‑מדריך חיפוש טקסט ב‑Postgres 2026.
מונחים במבט חטוף
Embedding — רשימה צפופה של מספרים בנקודה צפה שמיוצרים על‑ידי מודל, המייצגים קטע טקסט (או תמונה, אודיו וכו’) כנקודה במרחב בעל‑ממד גבוה. תוכן קשור סמנטית נוחת קרוב; תוכן בלתי קשור נוחת רחוק.
Lexical search — חיפוש המבוסס על התאמת מילים וטוקנים מדויקת. מהיר, דטרמיניסטי ונכון למונחים ידועים. אינו מבין מילות נרדפות, פרפרזות או מקבילים בין‑שפתיים.
Semantic search — חיפוש המבוסס על משמעות ולא על טוקנים. שאילתה כמו „איך מטפלים בטיימאוטים” יכולה להתאים למסמך שכותרתו „הגדרת מדיניות נסיונות חוזרים” ללא מילים משותפות, מכיוון שה‑embeddings שלהם קרובים גאומטרית.
Vector — רשימת מספרים. בהקשר של חיפוש, זה הפלט של מודל הטמעה. “חיפוש וקטורי” מוצא את הווקטורים הקרובים ביותר לווקטור השאילתה על‑פי מרחק גאומטרי.
FTS (Full-Text Search) — חיפוש מילולי מובנה של Postgres, מבוסס על tsvector / tsquery. מחלק לטוקנים, משורש ומשייך אינדקס לטקסט לשאילתות מילות‑מפתח. חזק עבור פרוזה וחיפוש מונחים מדויק; אינו מודע למשמעות.
BM25 — אלגוריתם דירוג לחיפוש מילולי (משמש ב‑Elasticsearch, Qdrant ועוד). מחשב ניקוד על‑פי תדירות המונח ומשקלל זאת לפי נדירות המונח בקורפוס. משופר מההתאמה הגולמית של מילות‑מפתח; עדיין מילולי.
HNSW (Hierarchical Navigable Small World) — אינדקס השכנות הקרובות המשוער הסטנדרטי לחיפוש וקטורי. בונה גרף קרבה מרובד לשאילתות דמיון מהירות ובקשת‑recall גבוהה. pgvector, Qdrant, Weaviate ורוב האחרים משתמשים בו.
RRF (Reciprocal Rank Fusion) — אלגוריתם למיזוג רשימות תוצאות מדורגות ממערכות אחזור מרובות. משתמש רק במיקום הדירוג — אין צורך בנרמול ניקוד. תוצאה שמדורגת גבוה גם ברשימת ה‑FTS וגם ברשימת ה‑vector מקבלת ניקוד משולב חזק יותר מזו שמופיעה רק באחת מהן.
מה חיפוש סמנטי עושה בפועל
הטמעות וקטוריות ממירות טקסט (או תמונות, אודיו וכדומה) לרשימת מספרים — נקודה במרחב בעל‑מימדים גבוהים. מודל הטמעה מאומן כך שטקסט בעל משמעות סמנטית קשורה ייפול קרוב באותו מרחב. „Dog” ו‑„canine” מסתיימים קרובים. „Running a marathon” ו‑„running a Python script” נפרדים מרחוק למרות שמכילים מילה משותפת.
חיפוש דמיון במרחב הזה מוצא מסמכים שה‑משמעות שלהם קרובה ביותר למשמעות של השאילתה, ללא תלות בחפיפה מדויקת של מילים.
זה אומר:
- „How do I configure request timeouts?” יכול להתאים למאמר שכותרתו „Setting connection limits and retry policies” — אין מילות‑מפתח משותפות, אך הרלוונטיות הקונספטואלית גבוהה
- „Something light for a summer evening” יכול להתאים להמלצת יין בלי שמופיע מילה כלשהי בתיאור המוצר
- שאילתה באנגלית יכולה להתאים למסמכים רלוונטיים בצרפתית, ספרדית או יפנית אם מודל ההטמעה אומן ברב‑לשוני
חיפוש לקסיקלי (tsvector, pg_trgm) לא יכול לעשות שום דבר מכיוון הזה. הוא פועל על מילים ותווים, לא על משמעות. הכלים אינם ניתנים להחלפה — הם פותרים בעיות שונות.
מתי pgvector מנצח
בניית RAG. Retrieval‑Augmented Generation משיגה את קטעי המסמך שהמשמעות שלהם קרובה ביותר לשאלת המשתמש, ואז מעבירה אותם למודל שפה כהקשר. שלב ההשגה הזה הוא פעולה וקטורית. חיפוש טקסט מלא (FTS) יפספס פרפרזות, מילים נרדפות והתאמות קונספטואליות שקטע רלוונטי עשוי לבטא בצורה שונה. היתרון של pgvector על פני מאגר וקטורים עצמאי: הוא רץ בתוך מופע ה‑Postgres הקיים שלך — אין צורך בשירות נפרד לפריסה, תפעול או סינכרון נתונים.
המשתמשים מתארים מה הם רוצים, לא מה לחפש. „מאמרים על בניית ביטחון עצמי כמנהל חדש” אין מילות‑מפתח שמופיעות באופן אמין בפוסטים הרלוונטיים. „מסגרת קלה לניהול תופעות לוואי” אולי לא תשתמש במילים המדויקות בתיעוד. חיפוש וקטורי תופס את הכוונה, לא את האיות.
מציאת פריטים דומים. מוצרים קשורים, כרטיסי תמיכה דומים, דוחות באגים משוכפלים, מאמרים שאולי תאהב גם. „מצא בעיות דומות לזו” הוא חיפוש שכנות‑קרובה — משבצים את הפריט, מוצאים את השכנים הגאומטריים שלו. אזהרה חשובה: חיפוש וקטורי תמיד מחזיר תוצאות, אפילו כשאין דבר דומה באמת. למקרים של dedup והמלצות, יש לסנן בעזרת סף מינימלי של דמיון (למשל, cosine similarity ≥ 0.80) כדי למנוע הצגת התאמות בעלות אמון נמוך כאילו הן משמעותיות.
דדופליקציה סמנטית. לפני אינדקסינג של תוכן ל‑RAG או לחיפוש, לרוב צריך לזהות כמעט‑שכפולים בקורפוס — מאמרים שעברו עריכות מרובות, כרטיסי תמיכה שהוגשו פעמיים, ערכי בסיס ידע שחופפים משמעותית. משבצים את המסמכים ומסננים בעזרת סף של cosine similarity כדי לסמן או למזג כמעט‑שכפולים לפני שהם מזהמים את האינדקס. זה מונע שהשגה תחזיר מספר קטעים כמעט‑זהים ותדלדל את חלון ההקשר.
חיפוש רב‑לשוני. מודלים רב‑לשוניים ממפים תוכן סמנטית‑שווה בין שפות לווקטורים קרובים. שאילתה בספרדית עבור „perder peso” יכולה להתאים למאמר באנגלית על „sustainable weight loss habits” — אין טוקנים משותפים, אך המשמעות זהה. FTS דורש קונפיגורציית מילון לכל שפה ומתמודד גרוע עם שאילתות חוצות‑שפה. pg_trgm הוא בלתי תלוי בשפה אך אורטוגרפי, לא סמנטי.
הקמת pgvector
מתקנת ההרחבה ועד שאילתת דמיון, ההגדרה היא כמה פקודות SQL:
CREATE EXTENSION IF NOT EXISTS vector;
ALTER TABLE documents ADD COLUMN embedding vector(1536);
-- HNSW הוא בדרך‑כלל האינדקס הראשון לנסות עבור מערכי נתונים בגודל בינוניCREATE INDEX documents_embedding_idx ON documents USING hnsw (embedding vector_cosine_ops);
-- שאילתת חיפוש סמנטיתSELECT id, title, 1 - (embedding <=> $1::vector) AS similarityFROM documentsORDER BY embedding <=> $1::vectorLIMIT 10;<=> הוא מרחק קוסינוס. 1 - cosine_distance נותן דמיון קוסינוס (1.0 = זהה, 0.0 = אורטוגונלי). עבור ivfflat (החלופה הישנה, המהירה יותר לבנייה), השתמשו ב‑lists = sqrt(row_count) כנקודת התחלה.
מה pgvector לא מתמודד איתו היטב
- התאמת טוקנים מדויקת — קודי מוצר, קודי שגיאה, שמות פונקציות.
ORD-12345אינו דומה סמנטית לשום דבר. חיפוש מבוסס הטמעה עלול להחזירORD-12344או לא להחזיר תוצאה רלוונטית. השתמשו ב‑FTS או באינדקס B‑tree. - שמות עצמאיים ושמות propr. מרחב ההטמעות מארגן לפי משמעות, לא לפי איות. רשומת המשתמש “Micheal Jordan” לא בהכרח תיפול קרוב ל‑“Michael Jordan” במרחב הווקטורים.
- מחרוזות קצרות שבהן דמיון ברמת תו חשוב יותר מהמשמעות.
pg_trgmמטפל בזה. - שאילתות שבהן חייב להופיע המונח המדויק. BM25 ו‑FTS אמינים יותר בהתאמה של מונחים ידועים.
חיפוש היברידי: למה שני הכלים יחד
תיעוד טכני הוא הדוגמה הברורה שבה אף כלי לבדו אינו מספיק.
משתמשים שמחפשים “how to configure timeouts” זקוקים להתאמה מושגית: מאמר שכותרתו “Setting retry policies and connection limits” אינו חולק מילות מפתח, אך בדיוק מה שהם צריכים.
אותם משתמשים מחפשים גם withRetry(), ECONNRESET, ו‑ERR_SOCKET_TIMEOUT. מחרוזות מדויקות אלו חייבות להופיע — התאמה סמנטית עלולה לא למצוא אותן באופן אמין, וחיובי שקר (דומה מושגית אך לא ה‑API הנכון) עלול להטעות.
חיפוש וקטורי מטפל בשאילתות המושגיות. FTS מטפל במונחים המדויקים. אף אחד מהם לא עושה את שני הדברים יחד בצורה טובה.
הפתרון הוא חיפוש היברידי: להריץ את שני המנועים ולמזג את התוצאות.
מיזוג דירוג הפוך (Reciprocal Rank Fusion)
Reciprocal Rank Fusion (RRF) הוא האלגוריתם הסטנדרטי לשילוב רשימות מדורגות ממערכות אחזור שונות. הוא אינו דורש נרמול ציון בין המערכות — הוא משתמש רק במיקומי הדירוג. תוצאה שמופיעה גבוה ב‑שתי הרשימות מקבלת ציון משולב חזק יותר מזו שמדומיננטת רק באחת.
WITH fts_results AS ( SELECT id, ROW_NUMBER() OVER (ORDER BY ts_rank(search_vector, query) DESC) AS rank FROM documents, to_tsquery('english', $1) query WHERE search_vector @@ query LIMIT 50),vector_results AS ( SELECT id, ROW_NUMBER() OVER (ORDER BY embedding <=> $2::vector) AS rank FROM documents ORDER BY embedding <=> $2::vector LIMIT 50),rrf AS ( SELECT COALESCE(f.id, v.id) AS id, COALESCE(1.0 / (60 + f.rank), 0) + COALESCE(1.0 / (60 + v.rank), 0) AS rrf_score FROM fts_results f FULL OUTER JOIN vector_results v ON f.id = v.id)SELECT d.id, d.title, rrf.rrf_scoreFROM rrfJOIN documents d ON d.id = rrf.idORDER BY rrf_score DESCLIMIT 10;המספר 60 במכנה הוא קבוע ה‑RRF. ערכים גבוהים מדכאים הבדלים במיקום הדירוג; ערכים נמוכים מגבירים אותם. ברירת המחדל של 60 עובדת טוב ברוב סוגי התוכן.
RRF חוסך את הבעיה הקשה של נרמול ts_rank (ציון תדירות‑לוגריתמית) מול מרחק קוסינוס (מדד גאומטרי). הם אינם ניתנים להשוואה. RRF שואל רק: „כמה גבוה הופיעה תוצאה זו בכל רשימה?“
חיפוש היברידי עם טריגרמים גם כן
לחיפוש שמוצג למשתמש על תוכן מעורב — שבו משתמשים עשויים לחפש שם של אדם, מושג, או מונח מדויק באותה סשן — מיזוג תלת‑כיווני מטפל בכולם:
WITH trgm_results AS ( SELECT id, ROW_NUMBER() OVER (ORDER BY similarity(title, $1) DESC) AS rank FROM documents WHERE title % $1 LIMIT 50),fts_results AS ( SELECT id, ROW_NUMBER() OVER (ORDER BY ts_rank(search_vector, to_tsquery('english', $1)) DESC) AS rank FROM documents WHERE search_vector @@ to_tsquery('english', $1) LIMIT 50),vector_results AS ( SELECT id, ROW_NUMBER() OVER (ORDER BY embedding <=> $2::vector) AS rank FROM documents ORDER BY embedding <=> $2::vector LIMIT 50),rrf AS ( SELECT COALESCE(t.id, f.id, v.id) AS id, COALESCE(1.0 / (60 + t.rank), 0) + COALESCE(1.0 / (60 + f.rank), 0) + COALESCE(1.0 / (60 + v.rank), 0) AS rrf_score FROM trgm_results t FULL OUTER JOIN fts_results f ON t.id = f.id FULL OUTER JOIN vector_results v ON COALESCE(t.id, f.id) = v.id)SELECT d.id, d.title, rrf.rrf_scoreFROM rrfJOIN documents d ON d.id = rrf.idORDER BY rrf_score DESCLIMIT 10;זה מטפל ב‑: התאמות שם גסות (טריגרמים), התאמות מילות‑מפתח מדויקות (FTS), ושאילתות מושגיות (וקטור). תיבת חיפוש יחידה יכולה לשרת את שלושת הכוונות של המשתמש.
ארכיטקטורות היברידיות מרובות שכבות
יישומים אמיתיים כמעט ולא כוללים משטח חיפוש יחיד. יש להם מספר משטחים, שלכל אחד צורך שונה:
| משטח | מה המשתמשים מחפשים | שכבות מומלצות |
|---|---|---|
| חיפוש בבלוג / תיעוד | מילות‑מפתח + מושגים | FTS + pgvector (RRF) |
| חיפוש שם משתמש / לקוח | שמות עם שגיאות כתיב | pg_trgm |
| חיפוש מוצר | שמות, תיאורים, “דומה ל‑” | pg_trgm + FTS + pgvector |
| זיהוי כפילויות בטיקטים של תמיכה | “בעיות דומות לזו” | pgvector בלבד |
| חיפוש SKU/הזמנה פנימי | מזהים מדויקים | אינדקס B‑tree |
| RAG על בסיס ידע גדול | שאלות בשפה טבעית | pgvector (מסמכים מחולקים לחלקים) |
| “ייתכן ותאהב גם” במסחר אלקטרוני | דמיון התנהגותי + סמנטי | pgvector |
| השלמת טקסט אוטומטית | קידומת, סובלנות לאיות | pg_trgm |
אלו אינם תרחישים היפותטיים. רוב היישומים העשירים בתוכן זקוקים לפחות לשני משטחים נפרדים עם צורות שאילתה שונות. הפיתוי הוא לבחור גישה אחת ולהשתמש בה בכל מקום — לרוב חיפוש וקטורי עכשיו, מכיוון שזה הבחירה האופנתית. זה מוביל לחישוב יקר של הטמעות עבור בעיות שבהן אינדקס טריגרם היה מהיר, זול ונכון יותר.
כלל האצבע
הוסף שכבה כאשר מופיע מצב כשל שהשכבה הנוכחית אינה יכולה לתקן:
- משתמשים מתלוננים על כך ששגיאות כתיב אינן מתאימות → הוסף
pg_trgm - משתמשים מחפשים לפי מושג ומפספסים תוצאות רלוונטיות → הוסף pgvector
- משתמשים מחפשים סמלים או קודים מדויקים ומקבלים תוצאות מושגיות במקום → הוסף FTS או בדוק אם אתה מסתמך יותר מדי על חיפוש וקטורי
- זמן השהייה הופך לבעיה → הערך סינון מוקדם, אינדקסים מקורבים, או חנות ייעודית
אם אתה באמת צריך חנות וקטורים ייעודית
pgvector מטפל ברוב חיפוש היישום לפני שאתה צריך מסד נתונים נוסף. הגבול המשוער תלוי במספר הווקטורים, הגדרות האינדקס, קצב הכתיבה, מסננים, חומרה וקונקורנטיות, ולכן יש להתייחס לכל “תחת 10 מיליון וקטורים” כנקודת התחלה לביצוע מדידות, ולא כמגבלה מוצרית. כאשר אתה באמת חורג — קונקורנטיות גבוהה מאוד, דרישות p99 latency נמוכות מאוד, מיליארדי וקטורים, או צורך בידוד רב‑שוכר רציני — נוף מסדי הנתונים הווקטוריים הייעודיים רחב ושווה לחקור.
מה המשמעות של עמודות המטריצה
חיפוש היברידי משמעותו שחיפוש מילות‑מפתח BM25 וחיפוש דמיון וקטורי מתבצעים באותה שאילתה, וממוזגים באמצעות RRF. ללא זאת, אתה או בוחר מודול חיפוש אחד או ממזג שני שאילתות בעצמך.
וקטורים מדללים הולכים מעבר ל‑BM25. וקטור מדולל של SPLADE מכיל כ‑30,000 ממדים (אחד לכל מונח במילון), כ‑98 % אפסים. המיקומים הלא‑אפסיים מצביעים על אילו מונחים חשובים ובאיזו משקל. שאילתה ל‑“dogs” גם תתן משקל ל‑“canine” ו‑“pet” — דיוק ברמת BM25 בתוספת הרחבת מונחים בתוך אינדקס וקטורי. אם העמודה הזאת אינה זמינה, תצטרך שכבת FTS נפרדת לשאילתות מונח‑מדויק.
# SPLADE: ~30,000 dims, ~60 non-zero — only relevant vocabulary positions firedef encode_splade(text: str) -> dict: tokens = tokenizer(text, return_tensors="pt", truncation=True, max_length=512) with torch.no_grad(): output = model(**tokens) vec = torch.log1p(torch.relu(output.logits)).max(dim=1).values.squeeze() return {"indices": vec.nonzero().squeeze().tolist(), "values": vec[vec != 0].tolist()}SQL / דמוי‑SQL הוא בעצם סינון. חיפוש וקטורי ללא סינון הוא רק הדגמה. עדיין תזדקק לתחום שוכר, טווחי תאריכים, הרשאות, וסינוני קטגוריות. SQL מלא (pgvector, LanceDB) מבטא זאת לצד ה‑joins הקיימים שלך. מסדי נתונים ייעודיים משתמשים באובייקטים של סינון JSON (Qdrant, Pinecone), DSL של שאילתות (Elasticsearch, Milvus) או GraphQL (Weaviate). הם עובדים; SQL נעשה מושך יותר ככל שהלוגיקה של הסינון מתסבכת.
-- pgvector: vector similarity is just another expressionSELECT id, title, 1 - (embedding <=> $1) AS scoreFROM documentsWHERE tenant_id = $2 AND category = ANY($3::text[]) AND created_at > NOW() - INTERVAL '90 days'ORDER BY embedding <=> $1LIMIT 10;# Qdrant: equivalent filter as a Python object — same result, more ceremonyresults = client.query_points( collection_name="documents", query=query_embedding, query_filter=models.Filter(must=[ models.FieldCondition(key="tenant_id", match=models.MatchValue(value=tenant_id)), models.FieldCondition(key="category", match=models.MatchAny(any=categories)), models.FieldCondition(key="created_at", range=models.DatetimeRange(gte=cutoff)), ]), limit=10,)טבעי רב‑מודלי משמעותו שהמסד משגר מודלי הטמעה לתוכן שאינו טקסט. אתה מעביר לו URL של תמונה גולמית; הוא מטפל בווקטוריזציה. רוב המסדים אינם תלויים במודל ההטמעה — אתה אחראי על צינור ההטמעה. Marqo ו‑Weaviate (דרך מודולי CLIP/ImageBind) סוגרים את הלולאה הזו.
# Marqo: POST raw images, query with text — no external embedding stepmq.index("products").add_documents( [{"id": "shoe-001", "image": "https://cdn.example.com/shoes/001.jpg"}], tensor_fields=["image"])results = mq.index("products").search(q="lightweight shoes for summer")# Returns shoe-001 despite zero keyword overlap — CLIP handles the cross-modal matchאינדקס מבוסס‑דיסק הוא מנוף עלות. אינדקסי HNSW במטמון RAM יכולים לדרוש כמה גיגה‑בייט של RAM לכל מיליון וקטורים של 1536 ממדים, כשמתחשבים בוקטורים הגולמיים, עומס הגרף והמטא‑דאטה. אלטרנטיבות נייטיב‑דיסק (Milvus DiskANN, Elasticsearch DiskBBQ, פורמט Lance של LanceDB, שכבת האובייקט של Turbopuffer) לעיתים מחליפות מעט זמן תגובה עבור עלות תשתית נמוכה יותר. בעומסי עבודה של RAG שבהם השהיית המודל כבר שולטת, פשרה זו שווה לרוב למדידה.
מקסימום ממדים הוא גורם שמסתתר במעבר ארכיטקטוני. text-embedding-3-large משתמש ב‑3072 ממדים, Jina v3 יכול להפיק הטמעות גדולות יותר, ומודלים מחקריים ממשיכים לדחוף גבוה יותר. שירותים מנוהלים מסוימים מפרסמים תקרות קשיחות לממדים; אחרים מתעדים תקרות גבוהות או אין תקרת פרקטית למודלים טיפוסיים. בדוק את התיעוד העדכני לפני שאתה מתחייב. בחר משהו עם מרווח; מעבר אינדקס וקטורי בגלל פגיעה בתקרת ממדים הוא ספרינט כואב.
נבדק לאחרונה מול תיעוד פרויקטים ציבוריים ודפי מוצר ב‑8 במאי 2026. התייחס לטבלה למטה ככלי עזר לקבלת החלטות, לא כתחליף לבדיקת המגבלות, המחירים והדגלים של שירותים מנוהלים.
הנוף
| מסד נתונים | פריסה | רישיון | חיפוש היברידי | וקטורים מדללים | SQL / דמוי‑SQL | רב‑מודלי | אינדקס דיסק | מקסימום ממדים | נקודת מתיקות |
|---|---|---|---|---|---|---|---|---|---|
| pgvector | אירוח עצמי / מנוהל (Supabase, Neon, RDS) | קוד פתוח (PostgreSQL) | ידני (RRF דרך SQL) | ❌ | ✅ SQL מלא | ❌ | ✅ HNSW על דיסק | 16,000 אחסון; 2,000 vector מאונדקס | כבר ב‑Postgres; ספירות וקטורים מתונות |
| Qdrant | אירוח עצמי / ענן | Apache 2.0 | ✅ BM25 נייטיב | ✅ תמיכה מבשילה | ❌ (REST/gRPC) | ❌ | ✅ | 65,535 | שאילתות מסוננות בקנה מידה; מטא‑דאטה מורכב |
| Weaviate | אירוח עצמי / ענן | BSD 3 | ✅ BM25 נייטיב + RRF | ✅ | ❌ (GraphQL / gRPC) | ✅ דרך מודולים | ✅ | 65,535 | תבניות גישה ב‑GraphQL; וקטוריזציה מובנית |
| Pinecone | ענן בלבד | קנייני | ✅ (התווסף 2024) | ✅ | ❌ | ❌ | ✅ (שרת‑ללא) | 20,000 | פשטות מנוהלת; ללא צוות תפעול |
| Milvus / Zilliz | אירוח עצמי / ענן (Zilliz) | Apache 2.0 | ✅ נייטיב | ✅ | ✅ דמוי‑SQL (Milvus Query Language) | ✅ | ✅ DiskANN | 32,768 | בקנה מידה של מיליארדים; ארגוני on‑prem |
| Chroma | משובץ / אירוח עצמי | Apache 2.0 | ❌ | ❌ | ❌ | ❌ | ❌ | 65,535 | פיתוח מקומי בלבד והדגמות |
| LanceDB | משובץ / ענן | Apache 2.0 | ✅ | ❌ | ✅ SQL דרך DataFusion | ✅ נייטיב | ✅ (פורמט Lance) | ללא הגבלה | קצה / serverless; אגם נתונים רב‑מודלי |
| Orama | משובץ / ענן | Apache 2.0 | ✅ טקסט מלא + וקטור | ❌ | ❌ | ❌ | ❌ | משתנה | אפליקציות JS/edge; חיפוש אתר/אפליקציה קל |
| Turbopuffer | ענן בלבד (שרת‑ללא) | קנייני | ✅ BM25 + וקטור | ❌ | ❌ | ❌ | ✅ (אחסון אובייקטים) | 16,000 | SaaS מרובה‑שוכרים; מיליוני מרחבי שם |
| Elasticsearch | אירוח עצמי / Elastic Cloud | SSPL / AGPLv3 | ✅ RRF + ELSER מדולל | ✅ (ELSER) | ✅ DSL של שאילתות | ❌ | ✅ DiskBBQ | 4,096 | כבר ב‑Elastic stack; חיפוש היברידי ארגוני |
| OpenSearch | אירוח עצמי / מנוהל AWS | Apache 2.0 | ✅ RRF + Neural Search | ✅ | ✅ DSL של שאילתות | ❌ | ✅ FAISS + HNSW | 16,000 | נייטיב ל‑AWS; אלטרנטיבה קוד פתוח ל‑Elastic |
| Vespa | אירוח עצמי / ענן | Apache 2.0 | ✅ נייטיב | ✅ טנסורים / דירוג לקסיקלי | ✅ YQL | ✅ טנסורים | ✅ | אפסית במידה מעשית | חיפוש + דירוג + מערכות המלצה |
| ClickHouse | אירוח עצמי / ענן | Apache 2.0 | ידני | ❌ | ✅ SQL מלא | ❌ | ✅ Columnar + HNSW | משתנה | אנליטיקה/לוגים עם חיפוש וקטורי לצד OLAP |
| MongoDB Atlas | ענן / אירוח עצמי | SSPL | ✅ מובנה | ❌ | ✅ MQL + אגגרגציה | ❌ | ✅ HNSW | 8,192 | כבר ב‑MongoDB; מסמך + וקטור באותו מקום |
| Redis (VSS) | אירוח עצמי / Redis Cloud | RSALv2 / SSPL | ✅ (RediSearch) | ✅ | ❌ | ❌ | ❌ RAM‑only | 32,768 | השהייה אפס‑אולטרה; שכבת קאש לחיפוש וקטורי |
| Marqo | ענן / אירוח עצמי | Apache 2.0 | ✅ | ❌ | ❌ | ✅ פוקוס נייטיב | ✅ | משתנה | רב‑מודלי קצה‑אל‑קצה: תמונה + טקסט + וידאו |
כמה דברים שלא מתאימים בטבלה
המרובה‑שוכרים של Turbopuffer בנויה סביב ספירות מרחבי שם גבוהות מאוד. המיצוב הציבורי וסיפורי הלקוחות מדגישים עומסים כמו הקורפוס הגדול והמרובה‑מרחבי‑שם של Notion. אם לכל משתמש או ארגון נדרש חיפוש וקטורי מבודד, ארכיטקטורה זו יכולה לשנות את הכלכלה, אך עדיין יש למדוד את הצורה של השוכרים שלכם.
מצב משולב של LanceDB הוא הדבר הקרוב ביותר ל-”SQLite לחיפוש וקטורי”. הוא פועל בתהליך, אינו דורש שרת, ועובד ב‑Lambda, Cloudflare Workers ובסביבות קצה. פורמט העמודות של Lance עושה את הפעולה המשולבת פרקטית בקנה מידה אמיתי.
Chroma מצטיינת בפיתוח/בדיקות ובהפצות אפליקציות קטנות. אם אתם שואפים לקורפוסים גדולים מאוד, זמינות גבוהה, פעילות כבדת‑דיסק, או חיפוש היברידי ברמה ראשונה, יש להעריך חנות מוכוונת ייצור לפני שמקודמים את האבטיפוס לתשתית.
Vespa היא הבחירה כשאחזור הוא רק חצי מהמוצר. היא משלבת אחזור לקסיקלי, חיפוש שכנים קרובים, טנסורים, ביטויי דירוג, קיבוץ והגשה בזמן אמת. הכוח הזה קיים, אך גם המורכבות התפעולית והמודלינגית. היא מתאימה יותר לצוותי חיפוש/המלצות מאשר ל-”להוסיף חיפוש סמנטי לאפליקציית CRUD שלי”.
ClickHouse נכנסת לשיחה כשחיפוש מצורף לניתוח. אם מקור האמת שלכם הוא אירועים, לוגים, עקבות או מדדים, ClickHouse שומרת מרחק וקטורי, סינון, צבירה, ואינדקס מלא‑טקסט רציני במנוע SQL אחד. אינה מסד נתונים וקטורי ייעודי, אך לעיתים היא התשובה המשעממת‑הנכונה לאחזור אנליטי.
וקטורים מדוללים הם הדרך לקבל התאמת מילות‑מפתח באיכות BM25 בתוך אינדקס וקטורי — ללא צורך במנוע טקסט מלא נפרד. Qdrant ו‑Elasticsearch מציעים יישומים בוגרים במיוחד כאן. אם חיפוש היברידי קריטי וארכיטקטורה של שני מערכות היא מחסום, תמיכת וקטורים מדוללים היא מה שיש לחפש.
בחירת הפתרון כש‑pgvector כבר לא מספיק
- מוצר SaaS עם בידוד לכל שוכר → Turbopuffer
- סינון מטא‑דאטה מורכב בקנה מידה → Qdrant
- כבר על ערמת Elastic/ELK → Elasticsearch עם DiskBBQ
- חנות AWS שרוצה קוד פתוח → OpenSearch
- פלטפורמת חיפוש/המלצות עם דרישות דירוג רציניות → Vespa
- אנליטיקה, תצפית, חיפוש לוגים/אירועים → ClickHouse
- קנה מידה של מיליארד‑על‑מיליארד במקומי / אירוח עצמי → Milvus
- קצה / ללא‑שרת / רב‑מודלי → LanceDB
- אפליקציית JS קטנה, אתר תיעוד, או חוויית חיפוש נייטיב‑קצה → Orama
- אפס תפעול, העלות משנית → Pinecone
- ראשון‑רב‑מודלי (תמונות, וידאו, אודיו) → Marqo
- כבר על MongoDB → Atlas Vector Search
- כבר על Postgres, צריך יותר מרחב → Supabase Vector או Neon (שניהם pgvector מנוהלים, עם כלי עבודה משופרים)
הדבר האחד שלא לעשות
אל תשתמשו בחיפוש וקטורי כחיפוש טקסט מעורפל עבור פריטים שיש להם תשובה נכונה.
“Find me the user with email dan@example.com” אינו בעיית חיפוש וקטורי. “Find the order with ID ORD-12345” גם אינו. הטמעת ORD-12345 וחיפוש לפי דמיון קוסינוס יחזירו משהו — אך ייתכן שהוא שגוי. למזהה יש תשובה נכונה. התאמה משוערת למזהה היא באג.
חיפוש וקטורי מחזיר את הפריט הדומה ביותר במאגר, גם כשאין דבר רלוונטי באמת. הוא אינו יודע מתי אין תשובה טובה. זה מקובל עבור מסמכים קשורים, אך בעייתי בחיפוש רשומה מדויקת, שבה תשובה בטוחה אך שגויה גרועה יותר מתוצאה ריקה.
הדבר תקף גם בכיוון ההפוך: אל תשתמשו ב‑FTS עבור שאילתות שבהן המשתמש מתאר מושג. “articles about making hard decisions under uncertainty” אינה מכילה מילות‑מפתח מהימנות. FTS יחזיר או רעש או כלום. השתמשו בכלי המתאים לצורת השאילתה.
התמונה המלאה
רוב מערכות החיפוש בתפעול דורשות יותר משכבה אחת:
pg_trgmלשמות, טעויות כתיב, השלמה אוטומטית- FTS /
pg_searchלחיפוש טקסט חופשי מבוסס מילות‑מפתח - pgvector לשאילתות סמנטיות וקונספטואליות
- RRF fusion למקרים שבהם משתמשים מערבבים סוגי שאילתות
- אינדקסים רגילים למזהים מדויקים, פילטרים ורשימות ממוינות
אלו אינם כלים מתחרים, אלא משלים זה את זה. מערכת חיפוש בנויה היטב בוחרת את השכבה המתאימה לכל צורת שאילתה — ובמקרים של חפיפה, מריצה כמה שכבות וממזגת את התוצאות.
הצוותים שמספקים תכונות חיפוש טובות מבינים את כל המערכת. אלו שלא, פונים למסד נתונים וקטורי, מטמיעים הכל, ותוהים מדוע חיפושי מזהים מדויקים לפעמים מחזירים רשומה שגויה.