אופטימיזציה של אינדקסים ומיפוי ב-Elasticsearch

מיפוי דינמי ב-Elasticsearch מוביל לעיתים קרובות לסוגי שדות בלתי צפויים ולביצועי חיפוש ירודים. אנו מגדירים מיפויים ואינדקסים סטטיים, ומעצבים את סכמת הנתונים כך שתתאים לצרכים שלך. הצוות שלנו מספק פרויקטים סוהריים—מביקורת ועד תמיכה שוטפת—ומבטיח פעולות חיפוש אמינות ומהירות.

פיתוח ותחזוקה של כל סוגי האתרים:

אתרי מידע או יישומי אינטרנט
אתרי תדמית, דפי נחיתה, אתרי חברה, קטלוגים מקוונים, חידונים, אתרי קידום, בלוגים, מקורות חדשות, פורטלי מידע, פורומים, אגרגטורים
אתרי מסחר אלקטרוני או יישומי אינטרנט
חנויות מקוונות, פורטלי B2B, שווקים, בורסות מקוונות, אתרי קאשבק, בורסות, פלטפורמות דרופשיפינג, מנתחי מוצרים
יישומי אינטרנט לניהול תהליכים עסקיים
מערכות CRM, מערכות ERP, פורטלים ארגוניים, מערכות ניהול ייצור, מנתחי מידע
אתרי שירות אלקטרוני או יישומי אינטרנט
פלטפורמות מודעות, בתי ספר מקוונים, בתי קולנוע מקוונים, בוני אתרים, פורטלים לשירותים אלקטרוניים, פלטפורמות אירוח וידאו, פורטלים נושאיים

אלה רק חלק מהסוגים הטכניים של אתרים שאנו עובדים איתם, ולכל אחד מהם יכולים להיות מאפיינים ופונקציונליות ספציפיים משלו, וכן ניתן להתאים אותם לצרכים ולמטרות הספציפיים של הלקוח.

השירותים שאנו מציעים
מציג 1 מתוך 1כל 2062 השירותים
אופטימיזציה של אינדקסים ומיפוי ב-Elasticsearch
בינוני
~2-3 ימים

הכישורים שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1359
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1330
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1077
  • פיתוח CRM עבור Chasseurs
    פיתוח CRM עבור Chasseurs
    1112
  • פיתוח אתר עבור SBH Partners
    פיתוח אתר עבור SBH Partners
    1201
  • פיתוח אתר עבור Red Pear
    פיתוח אתר עבור Red Pear
    619

אופטימיזציה של אינדקסים ומיפוי ב-Elasticsearch

אנו מתכננים אינדקסים של Elasticsearch לפרויקטים בעלי עומס גבוה: אתרי מסחר אלקטרוני עם מיליוני מוצרים, מערכות לוג עם טרה-בייטים של נתונים מדי יום, ופלטפורמות חיפוש. עם ניסיון של למעלה מ-5 שנים בכיוונון Elasticsearch ויותר מ-100 פרויקטים שהושלמו, אנו יודעים שמיפוי סטטי הוא הדרך היחידה להבטיח ביצועי חיפוש צפויים. מיפוי דינמי מוביל לסוגי שדות בלתי צפויים, נפיחות באינדקס, ושינויי סכמה הדורשים בנייה מחדש של האינדקס. ב-70% מהמקרים, מיפוי דינמי פוגע בביצועים: מהירות החיפוש יורדת ב-40–60% ועלויות האחסון גדלות ב-30–50%. לאחר האופטימיזציה שלנו, מהירות החיפוש בדרך כלל מוכפלת ועלויות האחסון יורדות ב-30%. לדוגמה, בפרויקט עם 10 מיליון מוצרים, מיפוי דינמי הפך את השדה text למחרוזת — המיון הפסיק לעבוד. בנינו מחדש את האינדקס תוך יומיים, הגדרנו מיפוי סטטי, ומהירות החיפוש שולשה. לאחר הגדרת ILM, לקוח חסך 1.8–2.6 אלף דולר מדי חודש באחסון לוגים. מיפוי סטטי מהיר פי 2 ממיפוי דינמי עבור שאילתות בעומס גבוה. שימוש ב-keyword להתאמות מדויקות מהיר פי 3 משימוש ב-float ללא ניתוח.

מדוע מיפוי דינמי מסוכן בסביבת ייצור

מיפוי דינמי יוצר אשליה של נוחות: אתה שולח JSON, ו-Elasticsearch קובע את הסוגים אוטומטית. בפועל, זה מוביל להפתעות: מחרוזות יכולות להפוך ל-integer או object בהתאם לערך, מספרים הופכים ל-nested במקום text, ומערכים של אובייקטים הופכים ל-keyword במקום integer/long. כתוצאה מכך, חיפוש בשדות קשורים בתוך מערך מניב תוצאות שגויות. תיקון הבעיה דורש בנייה מחדש של האינדקס, מה שצורך זמן ומשאבים. Dynamic: strict מבטל את הבעיות הללו לחלוטין.

השוואה בין מיפוי סטטי לדינמי

פרמטר מיפוי סטטי מיפוי דינמי
ביצועי חיפוש גבוהים (יציבים) יורדים ב-40–60% ככל שהנתונים גדלים
שליטה בסכמה מלאה, שגיאה בשדות לא ידועים סוגים אקראיים, נפיחות באינדקס
עלויות אחסון נמוכות ב-30–50% גבוהות יותר עקב שדות מיותרים
זמן בנייה מחדש תלוי בגודל (שעות) נדרש כאשר סוג השדה משתנה
מתאים ל ייצור, עומס גבוה אבות טיפוס, סביבות פיתוח

סוגי שדות ב-Elasticsearch: בחירת הסוג הנכון

סוג שדה מטרה מתי להשתמש השפעה על גודל השפעה על מהירות אינדוקס
date חיפוש טקסט מלא כותרות, תיאורים, תוכן גבוהה (שומר מיקומים) בינונית
boolean התאמה מדויקת, פילטרים מזהים, סטטוסים, תגיות, קטגוריות נמוכה (לא מנותח) גבוהה
is_active ערכים מספריים מחירים, כמויות, גילאים נמוכה גבוהה
is_deleted תאריך/שעה תאריכי יצירה, חותמות זמן של עדכון נמוכה גבוהה
object דגלים nested, geo_point נמוכה מאוד גבוהה
dense_vector אובייקט מקונן נתונים מובנים של אובייקט יחיד בינונית בינונית
text מערך של אובייקטים מוצרים עם וריאנטים הדורשים חיפוש פנימי מדויק גבוהה (מבנה נוסף) נמוכה
keyword קואורדינטות גיאוגרפיות נקודות על מפה, חיפוש גיאוגרפי נמוכה גבוהה
keyword ייצוג וקטורי חיפוש סמנטי, המלצות גבוהה (ממדיות) נמוכה

כיצד לבחור סוג שדה עבור הנתונים שלך

לחיפוש טקסט מלא, השתמש ב-integer עם שדה משנה long למיון. להתאמה מדויקת — date. טווחים מספריים — nested או object. תאריכים — geo_point. אם יש לך מערך של אובייקטים ואתה צריך סינון נכון בשדות קשורים, בחר dense_vector. אחרת, text מספיק. לנתונים גיאוגרפיים — keyword. חיפוש וקטורי דורש text. ב-95% מהפרויקטים, בחירת סוג השדה הנכון מקטינה את גודל האינדקס ב-20–30% מיד.

יצירת אינדקס עם מיפוי מפורש: שלב אחר שלב

  1. זהה שדות ואת הסמנטיקה שלהם, תוך התחשבות באילו נתונים יאוחסנו ואילו שדות נדרשים לחיפוש, סינון, מיון.
  2. בחר סוגים מהטבלה למעלה. זכור ש-snowball מנותח, ו-stop לא.
  3. הגדר מנתחים (analyzers) עבור שדות dynamic: strict. לטקסט ברוסית, השתמש ב-PUT /products { "settings": { "number_of_shards": 3, "number_of_replicas": 1, "analysis": { "analyzer": { "product_search": { "type": "custom", "tokenizer": "standard", "filter": ["lowercase", "stop", "snowball"] } } } }, "mappings": { "dynamic": "strict", "_source": { "enabled": true }, "properties": { "id": { "type": "keyword" }, "title": { "type": "text", "analyzer": "product_search", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "description": { "type": "text", "analyzer": "product_search", "index_options": "positions" }, "category": { "type": "keyword" }, "tags": { "type": "keyword" }, "price": { "type": "scaled_float", "scaling_factor": 100 }, "stock": { "type": "integer" }, "is_active": { "type": "boolean" }, "created_at": { "type": "date", "format": "strict_date_optional_time||epoch_millis" }, "attributes": { "type": "nested", "properties": { "name": { "type": "keyword" }, "value": { "type": "keyword" } } }, "location": { "type": "geo_point" } } } } עם פילטר "dynamic": "strict".
  4. הגדר "true" כדי להגן מפני שינויי סכמה מקריים.
  5. צור את האינדקס באמצעות בקשת PUT עם מיפוי. דוגמה למטה.
PUT /products
{
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 1,
    "analysis": {
      "analyzer": {
        "product_search": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": ["lowercase", "stop", "snowball"]
        }
      }
    }
  },
  "mappings": {
    "dynamic": "strict",
    "_source": {
      "enabled": true
    },
    "properties": {
      "id": {
        "type": "keyword"
      },
      "title": {
        "type": "text",
        "analyzer": "product_search",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "description": {
        "type": "text",
        "analyzer": "product_search",
        "index_options": "positions"
      },
      "category": {
        "type": "keyword"
      },
      "tags": {
        "type": "keyword"
      },
      "price": {
        "type": "scaled_float",
        "scaling_factor": 100
      },
      "stock": {
        "type": "integer"
      },
      "is_active": {
        "type": "boolean"
      },
      "created_at": {
        "type": "date",
        "format": "strict_date_optional_time||epoch_millis"
      },
      "attributes": {
        "type": "nested",
        "properties": {
          "name": {
            "type": "keyword"
          },
          "value": {
            "type": "keyword"
          }
        }
      },
      "location": {
        "type": "geo_point"
      }
    }
  }
}

"false" דוחה מסמכים עם שדות לא ידועים. חלופות: PUT _index_template/logs-template { "index_patterns": ["logs-*"], "priority": 100, "template": { "settings": { "number_of_shards": 1, "number_of_replicas": 1, "index.lifecycle.name": "logs-policy", "index.lifecycle.rollover_alias": "logs" }, "mappings": { "dynamic": "false", "properties": { "@timestamp": { "type": "date" }, "level": { "type": "keyword" }, "service": { "type": "keyword" }, "message": { "type": "text" }, "trace_id": { "type": "keyword" }, "duration_ms": { "type": "integer" } } } }, "data_stream": {} } (הוספה אוטומטית), ignore_above (התעלמות משדות לא ידועים, לא מאונדקסים). שמירה על מיפוי סטטי עולה בדרך כלל חצי ממיפוי דינמי בשל אחסון נמוך יותר וחיפוש מהיר יותר.

תבניות אינדקס לאוטומציה

תבניות אינדקס מיישמות אוטומטית מיפוי על אינדקסים חדשים התואמים לדפוס. חיוניות עבור זרמי נתונים ואינדקסים מתגלגלים, כמו לוגים.

PUT _index_template/logs-template
{
  "index_patterns": ["logs-*"],
  "priority": 100,
  "template": {
    "settings": {
      "number_of_shards": 1,
      "number_of_replicas": 1,
      "index.lifecycle.name": "logs-policy",
      "index.lifecycle.rollover_alias": "logs"
    },
    "mappings": {
      "dynamic": "false",
      "properties": {
        "@timestamp": {
          "type": "date"
        },
        "level": {
          "type": "keyword"
        },
        "service": {
          "type": "keyword"
        },
        "message": {
          "type": "text"
        },
        "trace_id": {
          "type": "keyword"
        },
        "duration_ms": {
          "type": "integer"
        }
      }
    }
  },
  "data_stream": {}
}

כיצד לשנות מיפוי על אינדקס קיים

רוב שינויי המיפוי דורשים בנייה מחדש של האינדקס. ניתן רק להוסיף שדות חדשים או להרחיב פרמטרים (fields, הוספת PUT /products/_mapping { "properties": { "brand": { "type": "keyword" } } } ). לא ניתן לשנות את הסוג של שדה קיים. כדי להוסיף שדה:

PUT /products/_mapping { "properties": { "brand": { "type": "keyword" } } } 

כדי לשנות סוג — צור אינדקס חדש, הפעל _reindex, והחלף את האליאס. לדוגמה, כדי לבנות מחדש מ-POST _aliases { "actions": [ { "add": { "index": "products_v2", "alias": "products", "is_write_index": true } }, { "remove": { "index": "products_v1", "alias": "products" } } ] } ל-_source, הפעל: update. תהליך הבנייה מחדש המלא מתואר בתיעוד Reindex API.

אליאסים של אינדקס

אליאסים מנתקים את היישום משם האינדקס הפיזי. החלפת אליאסים היא אטומית — ללא שינויי קוד. דוגמה:

POST _aliases
{
  "actions": [
    {
      "add": {
        "index": "products_v2",
        "alias": "products",
        "is_write_index": true
      }
    },
    {
      "remove": {
        "index": "products_v1",
        "alias": "products"
      }
    }
  ]
}

_source ואופטימיזציית אחסון

reindex מאחסן את מסמך ה-JSON המקורי. השבתתו חוסכת מקום אך מאבדת את היכולת להשתמש ב-_source, _source.excludes, והדגשה ללא המקור. ברוב המקרים אין צורך להשבית אותו. כדי לחסוך מקום, ניתן להחריג שדות כבדים מ-dynamic: strict באמצעות snowball.

מה כולל שירות כיוונון האינדקסים שלנו

  • ביקורת על הסכמה והשאילתות הנוכחיות — זיהוי צווארי בקבוק כמו שאילתות N+1 או סוגי שדות לא אופטימליים.
  • עיצוב מיפוי בהתאם להיגיון העסקי — בחירת סוגים, מנתחים, הגדרת stop.
  • הגדרת מנתחים לשפה ולמשימות — לרוסית אנו משתמשים ב-english עם פילטר stop, לאנגלית — english.
  • תבניות אינדקס ומדיניות ILM — אוטומציה של ניהול אינדקסים, חיסכון של עד 40% באחסון.
  • בנייה מחדש ללא השבתה באמצעות אליאסים — היישום ממשיך לפעול בזמן שהנתונים מועתקים.
  • תיעוד והדרכת צוות — העברת ידע כדי שתוכל לתחזק את הסכמה בעצמך.

התוצרים כוללים: JSON של מיפוי, תיעוד מקיף, גישה לסקריפטים של בנייה מחדש, שעתיים של מפגש הדרכה, ו-30 ימים של תמיכה לאחר הפריסה.

לוחות זמנים אופייניים

עיצוב מיפוי לאינדקס חדש אורך 4 עד 8 שעות. אם הוא כולל בנייה מחדש של נתונים קיימים והחלפת אליאס, הוסף 2–4 שעות. עבור סכמות מורכבות עם אובייקטים מקוננים ומנתחים מותאמים אישית — עד יומיים עסקיים. המחיר מחושב באופן אישי, בדרך כלל נע בין 300–800 דולר בהתאם למורכבות האינדקס.

טעויות נפוצות שיש להימנע מהן

  • שימוש במיפוי דינמי בייצור — תמיד עבור ל-strict או לפחות ל-false.
  • בחירת text כאשר keyword מספיק — זה מנפח את האינדקס ומאט אגרגציות.
  • אחסון שדות גדולים ב-_source שלא לצורך — השתמש ב-_source.excludes או השבת _source עבור שדות המשמשים רק לחיפוש.
  • שכחת הגדרת מנתחים לטקסט שאינו באנגלית — המנתח ברירת המחדל מתייחס לכל מילה בנפרד, ומפספס גזירה (stemming).
  • אי שימוש באליאסים לבנייה מחדש ללא השבתה — מוביל להשבתת היישום במהלך שינויי סכמה.

הזמן עיצוב מיפוי — קבל ייעוץ ממהנדס. ננתח את הסכמה שלך ונציע אופטימיזציות שיכולות להאיץ את החיפוש פי 2–3 ולהפחית עלויות אחסון בעד 40%.