Elasticsearch עבור אפליקציית מובייל: היכן החיפוש נשבר
חיפוש באפליקציה לעתים רחוקות מתוכנן מראש: בדרך כלל הוא צומח מבקשה מסוג «למצוא תת-מחרוזת בשם» אל מסד הנתונים הראשי. כל עוד בקטלוג יש מאות פריטים ושרת אחד, זה עובד בלי לשים לב. ברגע שהמגוון גדל והמשתמשים מתרבים, החיפוש הופך לצוואר בקבוק שמעכב גם את הקטלוג וגם את ביצוע ההזמנה.
נקודת הכשל הראשונה — רלוונטיות התוצאות. חיפוש לפי התאמה מדויקת לא מוצא מוצר כשיש שגיאת כתיב, סדר מילים שונה או הטיה: «נעלי ספורט לגברים» נמצא, «נעלי ספורט לגברים לריצה» — כבר לא.
Elasticsearch מכסה זאת על ידי פירוק השאילתה לצורות מילים, מילוני מילים נרדפות והתאמה מקורבת — אבל רק כאשר המנתחים, משקולות השדות וכללי העדיפות מוגדרים לקטלוג המסוים, ולא נשארים בברירת מחדל.
נקודת הכשל השנייה — השלמות אוטומטיות והשלמה מראש. כל הקשה שולחת שאילתה, והתור גדל מהר יותר מהקטלוג. חיפוש איטי כאן נראה מיד: המשתמש מקליד מילה, לא מקבל השלמות וסוגר את האפליקציה.
השלישית — עומס על צד השרת. שאילתות חיפוש מתחרות על אותם משאבים כמו עסקאות ותשלום: שליפות כבדות לפי תת-מחרוזת גוזלות כוח ממה שאמור להגיב באופן מיידי, וכך כל האפליקציה מתעכבת. לכן החיפוש מוציאים לשכבה נפרדת — מפרקים היכן בדיוק הוא נשבר ואיך זה נסגר.
האפקט מעיבוד מחדש של שכבת החיפוש: מהירות ודיוק
לפני העיבוד מחדש, החיפוש באפליקציה בוצע באמצעות שאילתות למסד הנתונים הראשי: כל תו שהוקלד יצר שליפה מכמה טבלאות עם השוואה לפי תבנית.
בעומסי שיא שאילתות כאלה התחרו בפעולות ביצוע ההזמנה, זמן התגובה של התוצאות עלה לשניות, וחלק מהפניות נפלו עקב חריגה מזמן ההמתנה — המשתמש ראה מסך ריק במקום תוצאות.
שכבת החיפוש הועברה ל-Elasticsearch ונבנו אינדקסים נפרדים למוצרים, לקטגוריות ולהשלמות. האינדקסים מתעדכנים לפי אירועי שינוי בקטלוג, בנייה מחדש מלאה מתבצעת ברקע ואינה חוסמת את התוצאות.
זמן התגובה הצטמצם בסדר גודל והפסיק להיות תלוי בנפח הקטלוג: מה שקודם לכן הידרדר עם גידול המגוון, כעת נשמר יציב.
דיוק התוצאות עלה בזכות שלושה מנגנונים. השלמה אוטומטית מציגה אפשרויות מהתווים הראשונים שהוקלדו, תיקון שגיאות כתיב קולט שאילתות עם טעויות בפריסת המקלדת ואותיות חסרות, ומילון מילים נרדפות מאחד ניסוחים שונים של אותו מוצר לתוצאה משותפת.
שיעור התוצאות הרלוונטיות בעשירייה הראשונה עלה משני שלישים לכמעט מלא — אנחנו מחשבים אותו על מדגם מתויג של שאילתות אמיתיות, ולא על תרחישי בדיקה.
אפקט נפרד — העומס שהוסר ממסד הנתונים הראשי. שאילתות חיפוש כבר לא מגיעות אליו, ולכן קפיצות שיא מטופלות בלי פגיעה בביצוע ההזמנות. נעלם סוג שלם של כשלים: תוצאות ריקות וקטיעות עקב חריגה מזמן המתנה במבצעים וברגעי תפוצות, שבעבר נסגרו בהרחבה ידנית.
שכבת החיפוש סופגת את הקפיצה בעצמה, וכאשר ההשלמות אינן זמינות התוצאות ממשיכות לעבוד במצב מצומצם במקום כשל מלא.
אפשרויות ארגון החיפוש: Elasticsearch וחלופות
חיפוש באפליקציה כמעט לעולם לא נבנה על טכניקה אחת: הבחירה תלויה בנפח הקטלוג, בדרישות לרלוונטיות ובמידת הסובלנות של האפליקציה לעיכוב בתגובה. להלן ארבע אפשרויות עבודה שבאמת בוחרים ביניהן, והמגבלות שלהן.
| אפשרות | מתי מתאימה | מגבלות |
|---|---|---|
| שאילתות למסד הנתונים הראשי | קטלוג של עד כמה אלפי רשומות, חיפוש לפי שם, אין דרישות לשגיאות כתיב | דירוג חלש של תוצאות; כל שאילתה מעמיסה על מסד הנתונים הטרנזקציוני |
| שירות חיפוש נפרד (Elasticsearch) | קטלוג גדול, חיפוש מקורב, מורפולוגיה, פאסטים, שגיאות כתיב | דרוש מערך משלו: אינדוקס, שכפול, ניטור; הנתונים חיים בפיגור ממסד הנתונים הראשי |
| מטמון השלמות | השלמה אוטומטית ושאילתות שכיחות, שבהן חשובה מיידיות | אינו מחליף חיפוש מלא: מכסה רק שאילתות פופולריות, דורש חימום ואיפוס בעת עדכון הנתונים |
| תכנית היברידית | הקטלוג גדל, החיפוש כבר הפך לצוואר בקבוק | תפעול מורכב יותר: שני מאגרים, סנכרון וכללים מה נחשב למקור האמת |
התכניות תואמות ומאפשרות מעבר: החיפוש מוסתר מאחורי ממשק אחיד של האפליקציה. התחלה בשאילתות למסד הנתונים, הוספת מטמון השלמות והעברה לשירות חיפוש נפרד אינן דורשות לכתוב מחדש את הלקוח — משתנה רק המימוש מאחורי הממשק. האינדוקס מתבצע באופן אסינכרוני ממסד הנתונים הראשי, ולכן החיפוש נשאר פעיל בזמן שנבנה אינדקס חדש.
שלבי הטמעה: מביקורת שאילתות ועד מסירה
חיפוש באפליקציה נשבר לעתים קרובות יותר לא ברגע חיבור המנוע, אלא בממשק שבין השניים: הביטויים שאנשים מקלידים אינם תואמים לאופן שבו הנתונים מתויגים. לכן אנחנו עובדים ברצף, וכל שלב מסתיים בארטיפקט שאפשר לבדוק לפני המעבר לשלב הבא.
- ביקורת שאילתות. אוספים ביטויי חיפוש אמיתיים מהלוגים ומתייגים לפי תרחישים — קטלוג, השלמה אוטומטית, שגיאות כתיב ופריסת מקלדת, שאילתות חוזרות. הפלט הוא מפת צווארי בקבוק: היכן התוצאות ריקות, היכן הרלוונטיות נכשלת, היכן המשתמש עוזב אחרי העמוד הראשון.
- סכמת אינדקסים. מתכננים מבנה לפי התיוג הזה: אילו שדות טקסטואליים, אילו ניתנים לסינון, היכן נדרשים מילים נרדפות, מורפולוגיה וטיפול בשגיאות כתיב. בנפרד מחליטים מה לשמור באינדקס ומה למשוך ממסד הנתונים הראשי, כדי שהנתונים לא יתפצלו.
- הגדרת התוצאות. ניתוח שפה, משקולות שדות, כללי דירוג לפי קטגוריות, עימוד והשלמות. את לוגיקת הרלוונטיות מתארים ומגרסאות — Elasticsearch כאן הוא מבצע, לא מקור הכללים.
- בדיקה על תנועה. את התוצאות החדשות מפעילים על חלק מהמשתמשים האמיתיים ומשווים לקודמות: שיעור השאילתות עם מעבר לכרטיס, מיקום המוצר המבוקש, זמן התגובה. החלטה על הפעלה מלאה מתקבלת לפי מספרים, לא לפי התרשמות.
- יכולת ניטור. מגדירים מדדים והתראות: שיעור תוצאות ריקות, שגיאות אינדוקס, פיגור בעדכונים. זו התראה מוקדמת במקום תלונות משתמשים.
- העברת תמיכה. מוסרים קונפיגורציות במאגר, סכמות, הוראות לאינדוקס מחדש ולחזרה לאחור, ומקיימים סקירה עם צוות הלקוח. זה גמור כאשר מילים נרדפות וכללים משתנים בלעדינו.
קונפיגורציות, סכמות אינדקסים ונהלי תחזוקה
החיפוש שאנחנו מגדירים נמסר יחד עם סט מלא של ארטיפקטים — לא «קופסה שחורה», אלא אוסף קונפיגורציות וכללים שלפיהם אפשר לפתח ולתחזק את המערכת בכוחות עצמכם. להלן מה בדיוק נשאר אצל הצוות שלכם לאחר המסירה.
- סכמות אינדקסים — מיפויים של שדות והגדרות מנתחים למורפולוגיה, שגיאות כתיב ותעתוק, עם הסבר מדוע השדה נשמר דווקא כך.
- כללי עדכון נתונים — מה ובאיזו תדירות נכנס לאינדקס, כיצד מטופלים מחיקות וכשלים חלקיים, כיצד מתבצע אינדוקס מחדש מלא ללא השבתה.
- קונפיגורציות סביבות — פרמטרים של סביבות פיתוח, בדיקות וייצור עם הבדלים מתוארים בבירור.
- נהלי תחזוקה — מה לעשות עם גידול הקטלוג, שינוי מבנה הכרטיסים ועדכון מתוכנן של המנוע.
- ניטור החיפוש — שיעור שאילתות ללא תוצאות, זמן תגובה, שיעור שאילתות עם מעבר להזמנה וספי הפעלה של התראות.
- גיבוי וחזרה לאחור — עותקים מלאים ומצטברים של אינדקסים, סדר השחזור וזמן החזרת החיפוש למצב עבודה.
- תיעוד — פריסה מאפס, מפת כשלים אופייניים ונקודות שבהן יש להסתכל קודם כול בעת הידרדרות.
כל סעיף נבדק בקבלה: אנחנו מראים כיצד להקים מערך מאפס לפי התיעוד ולשחזר את הקונפיגורציה. סט כזה אומר שאפשר לפתח ולתחזק את החיפוש באפליקציה בלעדינו — או יחד איתנו, כשנפח העבודה גדל.
מקרה בוחן: כיצד החיפוש בקטלוג הואץ לאחר עיבוד מחדש
קטלוג של כמה עשרות אלפי פריטים — זה המקרה שבו החיפוש מפסיק להיות פונקציה משנית. בשירות עם מגוון רחב, השאילתות הלכו ישירות למסד הנתונים הראשי: כל תו שהוקלד יצר שאילתה כבדה על כל טבלת המוצרים, ההשלמות חזרו תוך 1.5–2 שניות, והמוצר המבוקש נכנס לחמישייה הראשונה רק ב-38% מהשאילתות.
הסיבה לא הייתה רק מהירות. החיפוש לא הבין שגיאות כתיב, צורות מילים, מילים נרדפות ופריסת מקלדת לטינית, והעלה פריטים שהוסרו מהמכירה מעל פריטים עדכניים. התמיכה קיבלה זרם פניות «המוצר קיים, אבל החיפוש לא מוצא אותו».
מה עשינו
העברנו את החיפוש לאינדקס נפרד על Elasticsearch — מסד הנתונים הראשי הפסיק להיות צוואר בקבוק, והדירוג הפך לניהולי. הגדרנו מנתחים לקלט רוסי ולטיני: צורות מילים, מילים נרדפות, תעתוק, עמידות בפני שגיאות כתיב ורווחים מיותרים.
הוספנו בוסטינג לפי מלאי במחסן, פופולריות וחדשנות, כדי שפריטים נדירים ושהוסרו לא יעלו מעל פריטים נמכרים.
את התפעול סגרנו בנפרד: האינדקס מתעדכן באופן מצטבר בעת שינוי בקטלוג, בלי בנייה מחדש מלאה, וכאשר החיפוש אינו זמין האפליקציה מחזירה מטמון וקטגוריות רגילות במקום מסך ריק.
מדדים לפני ואחרי
| מדד | לפני | אחרי |
|---|---|---|
| זמן תגובת ההשלמות | 1.5–2 שניות | כ-0.2 שניות |
| המוצר המבוקש בחמישייה הראשונה | 38% מהשאילתות | 87% |
| פניות לתמיכה בנושא חיפוש | רמת בסיס | פי 4 פחות |
המעבר בוצע בלי לעצור את השירות. כעבור חודש החיפוש חדל להיות מקום שמפחיד להיכנס אליו: משתמשים מחפשים ישירות יותר, במקום לגלול בקטגוריות, ושיעור ההפעלות עם שאילתת חיפוש גדל בלי שינויים בממשק.
מה לעשות אם החיפוש כבר פרוס בכוחות עצמכם
אם החיפוש כבר עובד על אמצעים מובנים — שאילתות ישירות למסד הנתונים או אינדקס מקומי במכשיר — כדאי להתחיל לא משכתוב, אלא ממדידות. בודקים באיזה נפח קטלוג זמן התגובה מפסיק להיות נוח, כיצד התוצאות מתנהגות עם שגיאות כתיב, מילים נרדפות והחלפת פריסת מקלדת, ומה קורה למסד הנתונים בעומס שיא. המספרים האלה קובעים אם בכלל נדרש שירות חיפוש נפרד.
בהמשך מפרידים את הפונקציונליות לפי דרישות. השלמות לפי קלט, מסננים, מיון וחיפוש טקסט מלא עם דירוג — אלה משימות שונות, וחלקן נשאר בשקט בחיפוש המובנה. בדרך כלל יש טעם להוציא רק את תרחיש הטקסט המלא, שבו חשובים רלוונטיות, מורפולוגיה ועמידות בפני שגיאות קלט — את השאר אין צורך לגעת.
מעבר לשירות חיפוש כמו Elasticsearch נעשה בלי השבתה: האינדקסים מתמלאים במקביל לעבודת האפליקציה, המערך הישן ממשיך להשיב למשתמשים, והחדש מקבל את אותו זרם נתונים ומשיב במצב צללים.
אנחנו משווים את התוצאות על אותה קבוצת שאילתות, עד שהפערים מוסברים, ורק אחר כך מעבירים חלק מהתנועה — תחילה לעובדים פנימיים, ואחר כך לאחוז קטן מהקהל.
הצוות שלכם לא מושבת בתהליך: הוא מחזיק את הלוגיקה העסקית, כללי עיבוד הנתונים וסדרי העדיפויות של התוצאות, ואנחנו סוגרים את סכמת האינדקסים, השכפול, האינדוקס מחדש והתנהגות בעת כשלים. חזרה לאחור פירושה החזרת חלק התנועה והמערך הישן, שנשאר חי עד לרגע שבו המדדים של החדש יציבים. לכן מיגרציה בלי השבתה אינה הבטחה, אלא תוצאה של כך ששתי סכמות עובדות במקביל לזמן מה.
ספקות טכניים: שאלות של מהנדסים ומובילים טכניים
ספקות לגבי Elasticsearch באפליקציית מובייל מצטמצמים לחמישה נושאים: רעננות הנתונים באינדקס, התנהגות בעת כשל של שירות החיפוש, מדידות איכות התוצאות, גידול הנפח ותמיכה לאחר המסירה. נעבור על כל אחד.
עד כמה הנתונים בחיפוש רעננים?
השינויים נכנסים לאינדקס דרך תור, ולא בכתיבה ישירה ממסד הנתונים, ולכן כשל בחיפוש אינו חוסם הזמנות. הפיגור הוא שניות, בבניות מחדש המוניות של הקטלוג דקות, והגידול שלו נתפס בהתראה נפרדת.
מה יראה המשתמש בעת כשל בחיפוש?
מספר צמתים עם שכפולי שרדים — אובדן אחד אינו מפסיק את התוצאות. אם כל החיפוש אינו זמין, האפליקציה עוברת למסלול גיבוי: שאילתה למסד הנתונים לפי שדות מפתח עם מסננים בסיסיים במקום מסך שגיאה.
כיצד בודקים את איכות התוצאות?
לפני שחרור מריצים סט שאילתות ייחוס עם תוצאות צפויות ומחשבים שלמות ודיוק. בפרודקשן בודקים שאילתות בלי קליק ובלי ניסוח מחדש: אם הן גדלות — מתקנים מנתח, מילים נרדפות ומשקולות שדות.
האם החיפוש יעמוד בגידול נפח הנתונים?
השרדים מחולקים לפי זמן ולסוג תוכן: גידול הקטלוג אינו דורש אינדוקס מחדש מלא. הישן עובר לאינדקס קר עם פחות שכפולים, ונהל מחזור החיים מנקה אותו אוטומטית.
האם נוכל לתחזק את החיפוש בכוחות עצמנו?
מוסרים מיפויים, מנתחים, נהלי מחזור חיים, לוחות ניטור והתראות, ועוברים עם הצוות על פעולות אופייניות: להוסיף שדה, לבצע אינדוקס מחדש, לשנות דירוג. בהמשך אתם מנהלים את המערך בעצמכם.
נדון במשימה: ננתח את סכמת החיפוש ונחזור עם תכנית
שיחה על חיפוש במהירות הופכת למילים כלליות אם מגיעים אליה בלי עובדות.
כדי לדון במשימה באופן ענייני, מספיק מה שכבר קיים בפרויקט: תיאור סכמת האינדקס הנוכחית, ייצוא של שאילתות משתמשים אמיתיות, דוגמאות לתוצאות מוצלחות ולא מוצלחות, מגבלות בנוגע למידע אישי ונקודות שבהן האפליקציה פונה לשירות החיפוש.
- תרחישי חיפוש: השלמות תוך כדי הקלדה, תיקון שגיאות כתיב, חיפוש לפי מסננים ומיון;
- נפח הקטלוג, קצב העדכון שלו והדרישות לרעננות התוצאות;
- זמן התגובה הרצוי לשאילתה והתנהגות האפליקציה אם החיפוש אינו זמין;
- כללי גישה: אילו שדות גלויים לתפקידים שונים ומה אסור לאנדקס;
- קונפיגורציית Elasticsearch הנוכחית: אינדקסים, מנתחים לפי שפות האפליקציה, שכפולים;
- תכנית שחרור האפליקציה שאליה יש לקשור את העבודה.
בשיחה נעבור על הנתונים האלה וננתח היכן בדיוק אובדת הרלוונטיות: בניתוח הטקסט, בסט השדות, במשקולות או במטמון בצד האפליקציה. בנפרד נקבע כיצד האינדוקס מחדש יעבור בלי לעצור את החיפוש ובאיזו סכמה נחזור לאחור אם איכות התוצאות תידרדר.
נחזור עם תכנית עבודה: הרכב העבודה לפי שלבים, סדר השלבים, נקודות בקרה וקריטריוני קבלה — למשל, שיעור השאילתות שבהן המוצר או המסמך המבוקש נכנס לשלוש התוצאות הראשונות. תארו את המשימה בצורה חופשית — נחזור עם הערכה ותכנית.







