אנשים שואלים אותי הרבה פעמים איך הכי טוב, הכי נכון לנתח בעיות ביצועים בבסיס נתונים מסוג Oracle. למרות שתמיד אני פועל לפי מספר קווים מנחים לא תמיד ישנה דרך פעולה אחת שהיא הנכונה ואו הטובה ביותר, זה כמובן תלוי בסיטואציה ובבעיית הביצועים עצמה.
במסגרת המאמר הזה אנסה להכניס אתכם לראש שלי וכיצד אני פותר בעיות ביצועים. בואו ניקח דוגמה אמתית שהיתה לי אצל לקוח לפני מספר שנים. הלקוח התלונן על בעיה בתהליך באפליקציה שלו שמרכז הבעיה היא הכנסת רשומות חדשות לבסיס הנתונים ארכה זמן רב מידי.
מתחילים
דבר ראשון שעשיתי היה להפיק דוח AWR (מי שלא מכיר זה עולם ומלואו) :
דבר ראשון לקחתי Snapshot, הרצנו את התהליך האיטי ולקחנו Snapshot פעם נוספת, זה מאוד פשוט לקחת Snapshot פשוט השתמשו ב :
EXEC DBMS_WORKLOAD_REPOSITORY.create_snapshot;
לאחר שלקחנו Snapshot פעמים הפקתי דוח AWR:
@$ORACLE_HOME/rdbms/admin/awrrpt.sql;
שימו לב שכדאי לשמור אותו בפורמט HTML ולא Text.
הדבר הראשון שתפס את עיני היה ב-“Top 5 Events” כיכב לו ה-“ db file sequential read” מה שאומר שבזמן הרצת הפעולה הכבדה רוב הזמן "הלך" על גישה אקראית לטבלה ואו לאינדקס.
בניגוד למקרה בו אתה רואה שמבוצע Full Table Scan גישה עבודה אל מול אינדקסים היא מצב רצוי, אך גם לזה יש מחיר, ולכן במקרים בהם יש הרבה המתנה על “ db file sequential read” אני תמיד בודק את הדברים הבאים:
- האם יש יותר מידי אינדקסים על הטבלה מה שיכול להאריך משמעותית את הכנסת המידע לטבלה שכן יש לעדכן מספר רב של אינדקסים.
- האם לטבלה יש הרבה Foreign Keys לטבלאות אחרות דבר המכריח את Oracle לבדוק את ה-Integrity של המידע שעודכן / התווסף לטבלה עבור פעולת Insert.
- האם מוגדרים Trigger-ים על הטבלה
לאחר בדיקת הטבלה הבעייתית ראיתי שיש מספר אינדקסים על הטבלה, אין Foreign Keys ואו Triggers, עדיין לא היתה לי תשובה מדוע פעולת ה-Insert לוקחת הרבה זמן, אך האינדקסים המוגדרים על הטבלה הפכו להיות החשודים העקרים.
מציאת האינדקס אשר גורם לבעיה
על מנת למצוא את האינדקס הבעייתי בצעתי Trace ל-Oracle Session :
exec dbms_monitor.session_trace_enable;
ב-Trace היו לא מעט שורות הדומות לשורה הבאה:
WAIT #3183967846: nam=’db file sequential read’ ela= 4 file#=8 block#=3317 blocks=9 obj#=16789
מה שנתן לי את הרעיון לנסות ולמצוא אובייקט אשר מופיע הכי הרבה פעמים ב-Trace עם Wait Event כמופיע למעלה. לאחר מציאת מספר האובייקט מצאתי את האינדקס ע"י שימוש ב-DBA_OBJECTS לפי ה-OBJECT_ID כמובן.
הפתרון
לאחר שמצאתי שם האינדקס החשוד פשוט ביצעתו לו Disable והרצתי את התהליך פעם נוספת הפלא ופלא ביצועי התהליך השתפרו פלאים.
עכשיו כל מה שנותר לי זה להבין מדוע האינדקס הזה גורם לירידה כל לך משמעותית בביצועים, בכדי לא להעמיס בפרטים אקפוץ ישר לסוף האינקס הבעייתי היה מוגדר על שדה מספרי ארוך מאוד אשר הערכים בו חוללו בצורה אקראית, מה שגרםש האינדקס בכל פעולת Insert או Update לשדה הזה היה ארוך שכן Oracle היה צריך להכניס את הערך החדש מלמקום הנכון ב-Index מה שגרם לקריאה של ה-Index מהדיסק וכתיבה שלו מחדש.
במקרה הזה הפתרון היה פשוט – הלקוח שינה את הערכים בטור מערכים אקראיים לערכים עוקבים מה שגרם להורדה משמעותית בקריאת הבלוקים של האינדקס לזיכרון והביצועים השתפרו פלאים.
ועד לפעם הבאה, ביי
עודד
עודד רז
Latest posts by עודד רז (see all)
- MySQL For Oracle DBA’s – בסיסי נתונים, טבלאות ומשתמשים - 03/04/2016
- MySQL for Oracle DBA’s – התקנה וחיות אחרות - 27/01/2016
- MySQL for Oracle DBA’s – ארכיטקטורה ומנועים - 27/12/2015
השאר תגובה: