ייעול שאילתה...

ייעול שאילתה...

יש לי שאילתה די פשוטה:
SELECT c.[ID], ,a.[ID] as aID ,b.[ID] as bID ,a.[Name] as aName ,b.[Name] as bName FROM [c] INNER JOIN [tbl] a ON c.[aID]=a.[ID] INNER JOIN [tbl] b ON c.[bID]=b.[ID]​
הקשרים בין שתי הטבלאות מוגדרים כראוי, בטבלה tbl יש כמה אלפי רשומות, בטבלה tbl יש בסה"כ כ-90K רשומות, ועדיין - לשאילתה הזו לוקח 37 שניות (!) לרוץ
איך מייעלים?
 

s h i m s h o n

New member
תשובה

לא התבלבלת? מי זו tbl ומי זו tbl? אם את מבינה למה אני מתכוון... בכל מקרה, תבדקי היטב אינדקסים על טבלאות a ו-b וכן סטטיסטיקות (אם יש כזה דבר ב-DB שאת משתמשת). אם ישנם אינדקסים בטבלה C על עמודות aID או bID, וודאי שהם מנוטרלים בהרצת השאילתא, למשל ע"י הוספת פונקציה סתמית:
INNER JOIN [tbl] a ON IfNull(c.[aID], NULL) = a.[ID]​
ומחוץ להקשר - את בטוחה שנדרש פה INNER JOIN? לא מתאים יותר LEFT JOIN? זה גם יכול לסייע ב"סידור" ענייני הביצועים. בברכה, ש.
 
צודק,

c היא הטבלה שמכילה כ-90K רשומות. בסיס הנתונים הוא MSSQL 2005, ואכן מבחינת לוגיקה נדרש INNER JOIN. לא ממש הבנתי את המשפט "אם ישנם אינדקסים בטבלה C על עמודות aID או bID, וודאי שהם מנוטרלים בהרצת השאילתא, למשל ע"י הוספת פונקציה סתמית: INNER JOIN [tbl] a ON IfNull(c.[aID], NULL) = a.[ID] "
 

s h i m s h o n

New member
תשובה [2]

ה-DB יכול לבחור באחת מכמה דרכי ריצה (execution plan). למשל: 1. לעבור על כל רשומות C, ומשם לגשת לטבלה A לפי עמודה ID (הגיוני, כי יש על ID אינדקס). 2. לעבור על כל רשומות A, ומשם לגשת לטבלה C לפי עמודה aID (הגיוני, אם יש אינדקס על aID). איך ה-DB בוחר? לפי השיקולים שלו, הרבה בעזרת הסטטיסטיקות שיש לו על הטבלאות והאינדקסים. בד"כ כדאי להשאיר ל-DB את חופש הבחירה הזה, אבל ניתן לפעמים "לעזור"/לכפות עליו דרך שרצויה לנו. למשל, כאשר מפעילים פונקציה על עמודה מסוימת, ה-DB לא יכול להעזר באינדקסים המשתמשים בעמודה הזו. אני הייתי ממליץ לך לקרוא את התשובות של החבר'ה האחרים, שמבינים היטב MSSQL, (אם לא הבנת את תשובתם, לא להתבייש לשאול!) - זהו כיוון טוב ללמוד על ביצועים של שאילתות באופן כללי. בברכה, ש.
 

GeForce 5

New member
>>

מעיון מהיר נראה כי האינדקסים הדרושים: טבלת C - שני אינדקסים, אחד על aID השני על bID טבלת tbl - אינדקס אחד על עמודת ID בדקי פרגמנטציה של האינדקסים באמצעות DBCC SHOWCONTIG, אם את לא יודעת לנתח הציגי את ה-output כאן. בנוסף רצוי להציג את ה-execution plan כמו כן בדקי האם ה-db מוגדר כ-auto update statistics ושאלה אחרונה... האם השדות aID,bID,ID כולם מאותו data type?
 
בנוסף למה שאחרים כתבו

קיבלת מספר הצעות טובות לגבי אינדקסים ופעולות שיכולות לשפר את השאילתה. ההצעות שלי מהוות תוספת להצעות האחרות, ולא תחליף לאותן הצעות. כדאי לנסות למצוא מה גורם לשאילתה לרוץ הרבה זמן. תנסי להריץ את הפקודה set statistics io on לפני הרצת השאילתה. זה יגרום לכך שתקבלי נתונים על כמות פעולות I/O, שנעשו. במידה ויש הרבה פעולות I/O, זה יכול להסביר את זמן הריצה. סיבה אחרת יכולה להיות החזרה של עשרות אלפי רשומות. אין לך בשאילתה where clause, ואני לא יודע כמה רשומות חוזרות לך. עם חוזרות לך אלפי רשומות, אז צריך לקחת בחשבון גם את זמן החזרת הרשומות לclient וזמן הצגת הרשומות. תנסי לנטרל את החזרת הרשומות לclient ע"מ לבדוק מה לוקח יותר זמן - החזרת והצגת הרשומות או מציאת הרשומות (בגרסת 2005 ניתן לבצע את הבדיקה ע"י גישה לתפריט query--->query options במסך, שנפתח בוחרים results ומסמנים את הcheck box של האפשרות discard results after execution.) במידה וב2 הבדיקות את מקבלת מעט פעולות I/O והשאילתה מחזירה מספר קטן של רשומות, שמהירות קבלתן לא מהווה פקטור בזמן השאילתה, יכול להיות שיש לך בעיית blocking. כדי לבדוק את זה אפשר לנסות להשתמש בlock hint שנקרא nolock. שווה להשתמש בזה רק לבדיקה ע"מ לראות אם יש השפעה על זמן הריצה. במידה ויש צריך לקחת בחשבון את ההשפעות שיש לnolock על שאילתה לפני שמחליטים להשתמש בhint.
 
למעלה