Hunting N+1s and Killing Wasted Queries in Laravel
עבודה על ביצועים היא לרוב משעממת.
זה לא תמיד קשור לסיפורי גיבורים שבהם הפחתתם את השיהוי (latency) ב-80%. ברוב הימים, מדובר פשוט בניקוי. אתם מוצאים שאילתות שלא ידעתם שאתם מריצים. ואז, אתם מוחקים אותן.
אם אפליקציית ה-Laravel שלכם גדלה, סביר להניח שאתם נתקלים בשלוש הבעיות הללו.
- Hidden N+1 Queries
אי אפשר לתקן את מה שלא רואים. השתמשו בכלי כמו beyondcode/laravel-query-detector בסביבת הפיתוח המקומית שלכם. הוא יגיד לכם מתי אתם משתמשים בתבנית loop-and-lazy-load.
אל תריצו את זה ב-production. זה מוסיף overhead. רשמו (register) אותו רק כשהאפליקציה שלכם נמצאת במצב local או testing.
- Eager Loading Waste
אנשים נוהגים לפתור בעיות N+1 על ידי הוספת with(). אבל זה יוצר בעיה חדשה. אתם עלולים לבצע eager-load לקשר (relationship) שה-view שלכם כבר לא משתמש בו.
אם עיצוב מחדש מסיר עמודה מטבלה, עליכם להסיר את קריאת ה-with() המתאימה ב-controller שלכם. אתם משלמים על נתונים שאתם זורקים לפח.
התייחסו לכל eager load כאל דרישה (claim). אם אתם לא משתמשים בנתונים, הסירו את הדרישה.
- Recomputing the Same Data
ערכים מסוימים נשארים זהים לאורך כל ה-request. אם אתם מחשבים אותם מספר פעמים, אתם מבזבזים CPU. השתמשו ב-memoization כדי לפתור זאת.
Example:
protected ?string $defaultConnection = null;
public function getDefaultConnectionName(): string
{
return $this->defaultConnection ??= $this->resolveDefaultConnection();
}
האופרטור ??= מחשב את הערך פעם אחת ומשתמש בו מחדש לשאר ה-request.
- Dashboard Query Traps
לוחות בקרה (Dashboards) מריצים לעיתים קרובות שאילתת count() נפרדת עבור כל כרטיס (card). אם יש לכם שישה כרטיסים, אתם מריצים שש שאילתות.
במקום זאת, עשו שני דברים:
- קבצו את הספירות (counts) שלכם. קבלו את כל הסיכומים עבור טבלה אחת בשאילתה אחת.
- השתמשו ב-cache קצר. סטטיסטיקות של לוח בקרה לא חייבות להיות מעודכנות בשנייה. שמרו אותן ב-cache למשך חמש דקות.
מבקר אחד משלם את מחיר השאילתה. כל השאר מקבלים את התוצאה מה-cache.
Final Tip: Prevent Regressions
תהליכי ניקוי נכשלים אם מפתחים מוסיפים מחדש את הקוד הגרוע מאוחר יותר. השתמשו ב-Pest כדי לבצע assertion לכמות השאילתות שלכם. הגדירו תקרה (ceiling) לכמות השאילתות שדף יכול להריץ. אם מפתח יוסיף N+1, הבדיקה תיכשל.
אופטימיזציה היא בעיקרה עניין של הסרה. הסירו טעינות שלא בשימוש. הסירו ערכים המחושבים מחדש. הסירו שאילתות מיותרות.
