MongoDB Indexing Cookbook
למה?
ביצועים: אינדקס נכון מקטין זמן תגובה ועומס CPU/IO.
מיון יעיל: מאפשר
sortמהיר ללאin-memory sort.סקלביליות: מונע
COLLSCANיקר כשמאגר הנתונים גדל.
אינדקסים מומלצים
הדוגמאות מתייחסות לקולקציה לדוגמה בשם code_snippets (התאימו לשם אצלכם):
(user_id, created_at)– לדפדוף כרונולוגי לפי משתמש.(user_id, programming_language)– לסינון לפי שפה.(user_id, tags)– שדה מערך; מזרז סינון לפי תגיות.(user_id, is_favorite)– סינון מועדפים למשתמש.אינדקס
textעלfile_name,description,tags– לחיפוש טקסט.
מתכונים (Python / PyMongo)
from pymongo import ASCENDING, DESCENDING
coll = db["code_snippets"]
coll.create_index([
("user_id", ASCENDING), ("created_at", DESCENDING)
], name="user_created_at", background=True)
coll.create_index([
("user_id", ASCENDING), ("programming_language", ASCENDING)
], name="user_lang", background=True)
coll.create_index([
("user_id", ASCENDING), ("tags", ASCENDING)
], name="user_tags", background=True)
coll.create_index([
("user_id", ASCENDING), ("is_favorite", ASCENDING)
], name="user_favorite", background=True)
coll.create_index([
("file_name", "text"), ("description", "text"), ("tags", "text")
], name="text_file_desc_tags", background=True)
בדיקות explain (Mongo Shell)
// newer -> older feed for a given user
db.code_snippets
.find({ user_id: 123 })
.sort({ created_at: -1 })
.limit(20)
.explain('executionStats')
מה לחפש ב-explain?
stage: עדיף לראות
IXSCAN(סריקת אינדקס) ולאCOLLSCAN.totalDocsExamined / totalKeysExamined: מספרים נמוכים מצביעים על שימוש יעיל באינדקס.
executionTimeMillis: צריך לרדת משמעותית אחרי הוספת אינדקסים נכונים.
sortPattern: וודאו שהמיון נתמך ע“י האינדקס (ללא
SORTנוסף).
בדיקת קיום אינדקסים
// Mongo shell
db.code_snippets.getIndexes()
# PyMongo
coll.index_information()
שיטות עבודה מומלצות
התאימו את סדר העמודות באינדקס לסדר הסינון והמיון בפועל (prefix rule).
מיון יציב: אם אתם ממיינים לפי
created_atהוסיפו גם_idבסוף בעת צורך.Text Index יחיד: ב-MongoDB יש בדרך כלל אינדקס טקסט יחיד לכל קולקציה; רכזו שדות יחד.
הימנעו מאינדקסים מיותרים: כל אינדקס עולה בזיכרון ובכתיבה; מדדו לפני ואחרי.
Array Fields: אינדקס עולה על כל ערך במערך; טוב ל-
tags.התאימו לשאילתות אמיתיות: הסתכלו ב-logs/metrics ובנו אינדקסים לפי העומס.
דוגמאות נוספות
// חיפוש לפי תגיות + מיון חדש -> ישן
db.code_snippets
.find({ user_id: 123, tags: 'flask' })
.sort({ created_at: -1, _id: -1 })
.limit(20)
.explain('executionStats')
// חיפוש טקסטואלי
db.code_snippets
.find({ $text: { $search: 'pagination cursor' } })
.project({ score: { $meta: 'textScore' } })
.sort({ score: { $meta: 'textScore' }, created_at: -1 })
.limit(20)
.explain('executionStats')
Gotchas נפוצים
סדר מיון לא תואם לאינדקס יגרום ל-
SORTיקר בזיכרון.Text Index קיים: אי אפשר ליצור שני אינדקסים טקסטואלים שונים על אותה קולקציה.
Regex עם Wildcard בתחילה (
/^.*abc/) לא ינצל אינדקס רגיל.סינון על שדה לא ממופתח יגרור
COLLSCANגם אם המיון ממופתח.שינוי סכימה: אם שדות עוברים שינוי שם, עדכנו גם את האינדקסים.