כדי לפתור בעיות שקשורות לשאילתות איטיות, משתמשים בQuery Explain כדי לקבל את תוכנית הביצוע של השאילתה ואת פרופיל הביצוע בזמן הריצה. בקטע הבא מפורטים השלבים שאפשר לבצע כדי לשפר את ביצועי השאילתות, בהתאם לפרופיל הביצוע:
הגבלת מספר התוצאות
משתמשים בשדה 'רשומות שהוחזרו' בעץ הביצוע כדי לזהות אם השאילתה מחזירה הרבה מסמכים. מומלץ להגביל את מספר המסמכים שמוחזרים באמצעות פסקה $limit. כך מצטמצם גודל הבייטים של התוצאות בסדרות, כשהן מוחזרות ללקוחות ברשת. במקרים שבהם הצומת Limit קודם לצומת MajorSort, מנוע השאילתות יכול לאחד את הצמתים Limit ו-MajorSort ולהחליף מימוש מלא בזיכרון ומיון במיון TopN, וכך להקטין את דרישת הזיכרון של השאילתה.
הגבלת גודל מסמך התוצאה
כדי להימנע מאחזור שדות לא נחוצים, כדאי להגביל את גודל המסמך שמוחזר באמצעות סעיף $project. כך אפשר לצמצם את העלות של המחשוב והזיכרון שנדרשים לעיבוד תוצאות הביניים, ואת גודל הבייטים של התוצאות כשהן מוחזרות ללקוחות ברשת. במקרים שבהם כל השדות שאליהם מתייחסת השאילתה מכוסים על ידי אינדקס רגיל (לא אינדקס מרובה מפתחות), זה גם מאפשר לסרוק את האינדקס באופן מלא בלי צורך לאחזר מסמכים מהאחסון הראשי.
שימוש באינדקסים
כדי להגדיר ולבצע אופטימיזציה של אינדקסים:
זיהוי אם השאילתה משתמשת באינדקס
כדי לזהות אם השאילתה משתמשת באינדקס, בודקים את צמתי העלה בעץ הביצוע. אם צומת העלה של עץ הביצוע הוא צומת TableScan, המשמעות היא שהשאילתה לא משתמשת באינדקס וסורקת מסמכים מהאחסון הראשי. אם נעשה שימוש באינדקס, בצומת העלה של עץ הביצוע יוצגו מזהה האינדקס ושדות האינדקס של האינדקס.
איך בודקים אם אפשר לבצע אופטימיזציה לאינדקס שבו נעשה שימוש
אינדקס שימושי לשאילתה אם הוא יכול להפחית את מספר המסמכים שמנוע השאילתות צריך לאחזר מהאחסון הראשי, או אם סדר השדות שלו יכול לספק את דרישת המיון של השאילתה.
אם נעשה שימוש באינדקס לשאילתה, אבל מנוע השאילתות עדיין מאחזר ומוחק הרבה מסמכים, כפי שמצוין על ידי צומת סריקה שמחזיר הרבה רשומות ואחריו צומת סינון שמחזיר מעט רשומות, זה סימן לכך שפרדיקט השאילתה שסופק באמצעות האינדקס לא סלקטיבי. כדי ליצור אינדקס מתאים יותר, אפשר לעיין במאמר יצירת אינדקסים.
אם נעשה שימוש באינדקס שאינו מרובה מפתחות בשאילתה, אבל מנוע השאילתות עדיין מבצע סידור מחדש בזיכרון של קבוצת התוצאות, כפי שמצוין על ידי צומת MajorSort בעץ הביצוע של השאילתה, זהו סימן לכך שאי אפשר להשתמש באינדקס כדי לספק את דרישת המיון של השאילתה. כדי ליצור אינדקס מתאים יותר, אפשר לעיין בקטע הבא.
אופטימיזציה של שאילתות $lookup
אפשר לבצע אופטימיזציה של שאילתות $lookup על ידי הוספת אינדקסים לאוסף from, וכך לאפשר לפעולה למצוא ביעילות מסמכים תואמים בלי לסרוק את האוסף כולו.
$lookup עם localField ועם foreignField
אם אתם משתמשים באפשרויות localField ו-foreignField בשלב $lookup, צריך ליצור אינדקס ב-foreignField באוסף from.
$lookup עם צינורות עיבוד נתונים בתוך צינורות עיבוד נתונים
אם אתם משתמשים באפשרות pipeline בשלב $lookup עם $match שלבים, כדאי ליצור אינדקס בשדות שקשורים לאוסף החיצוני כדי להימנע מסריקה מלאה של האוסף:
- בשלבים
$matchעם סמנטיקה של מסננים (לדוגמה{$match: {a: true}}), יוצרים אינדקס בשדות שמשתתפים בקולקציה החיצונית (a). - לשלבי
$matchעם סמנטיקה של צבירה שמשווה שדה עם ערך קבוע (לדוגמה,{$match: {$expr: {$gt: [a, 10]}}}) או עם השוואות שוויון (eqאוin) בין שדות ומשתנים שמוגדרים ב-let(לדוגמה,{$match: {$expr: {$eq: [a, "$$a"]}}}), צריך ליצור אינדקס בשדות שמשתתפים באוסף החיצוני. שימו לב שהאינדקס עם כמה מפתחות לא ישמש בתכנון.
יצירת אינדקסים
פועלים לפי ההוראות בתיעוד לניהול אינדקסים כדי ליצור אינדקסים. כדי לוודא שהשאילתה יכולה להשתמש באינדקסים, צריך ליצור אינדקסים רגילים (לא Multikey) עם שדות בסדר הבא:
- כל השדות שישמשו באופרטורים של שוויון. כדי למקסם את הסיכוי לשימוש חוזר בשאילתות, כדאי לסדר את השדות בסדר יורד לפי מספר הפעמים שהם מופיעים באופרטורים של השוואה בין שאילתות.
- כל השדות שייכללו במיון (באותו סדר).
- שדות שישמשו באופרטורים של טווח או אי-שוויון בסדר יורד של סלקטיביות אילוצי השאילתה.
- שדות שיוחזרו כחלק משאילתה באינדקס: הכללת שדות כאלה באינדקס מאפשרת לאינדקס לכסות את השאילתה ולמנוע את הצורך באחזור מסמך מהאחסון הראשי.
לשאילתות שכוללות סינון ומיון של שדות מערך, כדאי ליצור אינדקסים עם כמה מפתחות.
שימוש ברמז לשאילתה
אם יצרתם אינדקס מתאים יותר לשאילתה, אבל מנוע השאילתות לא משתמש באינדקס הזה, אתם יכולים לבטל את העדפת האינדקס של מנוע השאילתות באמצעות רמז לשאילתה.
מידע נוסף על הפלט של שאילתה שהופעלה באמצעות Query Explain זמין במאמר הפניה להפעלת שאילתות.