אינדקס ב־PostgreSQL מתחיל בשאילתה, לא בעמודה
איך מתכננים אינדקס לצורת גישה אמיתית, בודקים תכנית ביצוע ומבינים גם את המחיר בכתיבה.
״יש תנאי WHERE על העמודה, נוסיף אינדקס״ הוא כלל אצבע חלקי. אינדקס עוזר למסד הנתונים להגיע לנתונים, אבל התועלת תלויה בצורה שבה מבקשים אותם, בכמות השורות המתאימות ובעלות הקריאה לעומת הסריקה. צריך להתחיל מהשאילתה ומהתפלגות הנתונים, לא משם של שדה.
נשתמש בדוגמה של מסך הזמנות: המשתמש רוצה את עשרים ההזמנות האחרונות בחשבון מסוים ובסטטוס פתוח. זאת צורת גישה מוגדרת. האם אותו מסך צריך גם ספירה מלאה? האם החשבונות דומים בגודלם? האם רוב ההזמנות פתוחות? התשובות משפיעות על התכנון.
מתארים את הגישה לפני שבונים
SELECT id, created_at, total
FROM orders
WHERE account_id = $1 AND status = 'open'
ORDER BY created_at DESC, id DESC
LIMIT 20;
כאן יש סינון לפי חשבון וסטטוס, סדר יציב ומספר תוצאות קטן. אינדקס מורכב הוא מועמד טבעי לבדיקה, אבל לא מסקנה אוטומטית. סכמו אילו שאילתות נוספות יצטרכו את אותו מבנה, וכמה מהטבלה הוא יכסה. אינדקס שמצוין למסך אחד עלול כמעט לא לעזור לדוח רוחבי.
סדר העמודות הוא חלק מההחלטה
ב־B-tree מורכב, תנאי שוויון על העמודות המובילות והטווח הראשון שאחריהם חשובים לצמצום האזור הנסרק. תיעוד PostgreSQL מסביר את הכלל ואת האפשרויות הנוספות בגרסאות חדשות. אל תהפכו אותו לסיסמה שלפיה לעולם אי אפשר להשתמש באינדקס כשחסר התנאי הראשון.
CREATE INDEX orders_account_status_created_idx
ON orders (account_id, status, created_at DESC, id DESC);
זהו מועמד לדוגמה, לא המלצה להעתקה לכל מערכת. אם שאילתות נפוצות מחפשות את כל הסטטוסים יחד, ייתכן שצריך מבנה אחר. אם רק חלק קטן מההזמנות פתוחות, אפשר לבדוק אינדקס חלקי — תוך וידוא שהתנאי בשאילתה מאפשר למתכנן להשתמש בו.
קוראים תכנית ביצוע כמו השערה
EXPLAIN מציג את תכנית הביצוע המשוערת. EXPLAIN ANALYZE מריץ בפועל את השאילתה ומוסיף מדידה, ולכן צריך להשתמש בו בזהירות, במיוחד עם כתיבה. בדקו כמה שורות נסרקו, כמה הוחזרו, האם יש מיון נוסף והאם ההערכה רחוקה מהמציאות.
סריקה מלאה אינה בהכרח כישלון. אם השאילתה מחזירה חלק גדול מהטבלה, ייתכן שהיא זולה יותר מאוסף גישות אקראיות. גם זמן ריצה טוב על מחשב ריק אינו הוכחה לביצועים תחת עומס. תכניות משתנות עם נפח הנתונים, סטטיסטיקות ומאפייני פרמטרים.
Index Only אינו ״אין קריאת טבלה לעולם״
לפעמים כדאי לכלול עמודות תוצאה באינדקס כדי לצמצם גישות לטבלה. גם אז, האפשרות להימנע מגישה ל־heap תלויה בין היתר במידע הנראות של PostgreSQL. השם Index Only Scan אינו הבטחה שכל ביצוע ייגע רק באינדקס.
הוספת כל העמודות דרך INCLUDE יכולה להגדיל מאוד את האינדקס. בדקו אם השאילתה באמת חמה מספיק כדי להצדיק זאת. אם שדה רחב משתנה לעיתים קרובות, מחיר התחזוקה עשוי להיות משמעותי ביחס לחיסכון בקריאה. ההחלטה הנכונה נמדדת במכלול העומס.
המחיר שלא מופיע בצילום של השאילתה
כל אינדקס צורך מקום ומוסיף תחזוקה בכתיבה. הרבה אינדקסים דומים יכולים להכביד על inserts ו־updates ולסבך שינויי schema. תכננו גם את אופן היצירה במערכת פעילה: משך העבודה, נעילות, מקום פנוי ותהליך התאוששות במקרה של כישלון.
לפני הסרה, בדקו שימוש לאורך חלון שמכסה גם עבודות תקופתיות. אינדקס שנראה לא בשימוש במשך יום יכול להיות חיוני לסגירת חודש. השוו תועלת עסקית, לא רק מונה קריאות. תעדו מדוע הוספתם אינדקס כדי שהאדם הבא יוכל להעריך אם ההנחות עדיין נכונות.
תרגיל שאפשר לבצע מקומית
צרו נתוני בדיקה שבהם חשבון אחד מכיל הרבה יותר הזמנות מהאחרים. הריצו את השאילתה עבורו ועבור חשבון קטן, לפני ואחרי האינדקס. השוו תכנית, מספר שורות וזמן. לאחר מכן שנו את הסינון לסטטוס נפוץ ובדקו מה משתנה.
התוצר הרצוי הוא הסבר: באילו תנאים האינדקס עוזר, מה הוא עולה ומתי תבדקו אותו מחדש. זו גם תשובה טובה יותר בראיון מאשר ״B-tree הוא מהיר״. להמשך על חשיבה במונחי אילוצים, קראו על תכנון Cache.
להפוך הבנה לתרגול.
עוד כלים ללמידה עצמאית, או ליווי אישי שעובד על האתגרים שלכם.
עוד כיוון למחשבה.
איך להשתמש ב־AI בלי לוותר על שיקול דעת הנדסי
דרך עבודה שמנצלת יצירת קוד והסברים, ומשאירה אצלכם את ההבנה, הבדיקה והאחריות להחלטות.
לקריאת המאמרתור הודעות לא מעלים כשל: לתכנן retries וצרכנים אמינים
מסירה חוזרת, backoff, הודעות רעילות וגבולות transaction — השאלות שצריך לשאול לפני שמוסיפים Queue.
לקריאת המאמראיך מציגים פרויקט Backend בלי ללכת לאיבוד בפרטים
מסגרת מעשית להצגת פרויקט: מהבעיה העסקית, דרך ההחלטות שלך, ועד לתוצאות ולשאלות העומק.
לקריאת המאמר