none
שאילתא עם תנאי תאריך על ידי משתנה או תאריך מפורש RRS feed

  • שאלה

  • אני כותב כך: select * from tbl where dt between @t1 and @t2  ואז הOptimizer לא משתמש באינדקס של dt.

    רק אם אני כותב select * from tbl where dt between '2011/08/01' and '2011/08/02' אז יש שימוש באידקס.

    מה יכולה להיות הסיבה

    יום חמישי 01 ספטמבר 2011 16:03

תשובות

  • אם הבנתי נכון את הבעיה אז היא לא קשורה למה שהצגת בהסבר (כמובן שיכול להיות שאני לא הבנתי אותו ונחכה לשואל השאלה). מה שאני הבנתי מהשאלה זה שעבור אותם נתונים של סינון השימוש בפרמטרים מייצר תוכנית הרצה שונה מאשר שימוש ישיר (וזה דיי ברור). מדובר על אותו אופן הרצה ואותם נתונים כשכל ההבדל הוא שימוש בפרמטרים או שימוש בערך מפורש.

    למשל 2 השאילתות האלא מייצרות תוכנית הרצה שונה (זו לא דוגמה זהה סתם להמחיש הבדל עם ובלי שימוש בפרמטר), למרות שהן כביכול זהות ובטח שהן זהות מבחינת הסינון תאריכים (באחד פשוט אין שימוש בפרמטר ובשני יש):

    use Northwind
    go

    select * from Orders
    where OrderDate between '1996-07-04 00:00:00.000' and '1996-07-11 00:00:00.000'
    GO

    declare @D1 as datetime = '1996-07-04 00:00:00.000'
    declare @D2 as datetime = '1996-07-11 00:00:00.000'
    select * from Orders
    where OrderDate between @D1 and @D2
    GO

    לא זה מה שהוא שאל?!?

    • סומן כתשובה על-ידי Ami Levin יום שני 05 ספטמבר 2011 12:59
    יום שישי 02 ספטמבר 2011 15:23
    מנחה דיון

כל התגובות

  • שאילתה דינאמית :-)

    דרך אגב אם היית מעביר לנו את מבנה הטבלה שלך וכמה נתונים לדוגמה (נסה לשחזר את הבעיה) אז היה הרבה יותר קל להביא לך פתרון והסברים יותר מדוייקים על המקרה שלך

    1. תנסה לבדוק את תוכנית ההרצה האמיתית ולא התוכנית המצופה (יש כפתור ב SSMS להציג חלון של תוכנית ההרצה האמיתית ואז כשאתה מבצע הרצה אתה מקבל בנוסף לחלון התוצאות וחלון ההודעות גם חלון של תוכנית הרצה אמיתית שנעשה בה שימוש... זה כפתור אחר מזה שעושים בו שימוש לתוכנית הרצה מצופה).

    2. לעיתים כשאין למנוע המיטוב ערך אלא משתנה דינאמי מנוע המיטוב אכן לא יכול לבצע תוכנית הרצה אידאלית. זה קורה הרבה פעמים ב SP למשל שמקבל נתונים (עד שהוא בונה את הסטטיסטיקות)

    3. אני מניח שאתה עושה שימוש ב non-clustered index. אם כן החלפה ב clustered index יכולה לעזור לך. ממליץ לבדוק.

    4. אתה יכול אולי לנסות לעבוד עם hinting כדי להכריח עבודה כמו שאתה רוצה

     

    הנה דוגגמה קטנה רק להמחשה של שימוש בפרמטרים והבדל שנוצר (זה לא המקרה שלך אלא רק המחשה..תעתיק את הקוד לקובץ כדי לראות את התוכן טוב):

    use Northwind
    go

    -- שלושת הדוגמאות הבאות מראות כיצד כמות הנתונים שבוחרים משפיע על תוכנית ההרצה
    -- דווקא בחירת מספר מועט של נתונים גררה במקרה המסויים כאן יותר עבודה ולא פחות
    -- שאילתה ראשונה ואחרונה הן של 33 אחוז בעוד האנמצעית של פחות נתונים לוקחת 34 אחוז
    select * from Orders

    select * from Orders
    where OrderDate between '1996-07-04 00:00:00.000' and '1996-07-11 00:00:00.000'

    select * from Orders
    where OrderDate between '1996-07-04 00:00:00.000' and '1997-02-18 00:00:00.000'

    GO

    -- כשעובדים עם פרמטרים השרת לא יודע מראש אם יותאם האפשרות השנייה או השלישית ולכן הוא מבצע את הפעולה בהתאם (קיבלנו את השימוש בתוכנית ההרצה של הפעוןלה השלישית למרות שהפרמטרים זהים לערכים במקרה השני)
    declare @D1 as datetime = '1996-07-04 00:00:00.000'
    declare @D2 as datetime = '1996-07-11 00:00:00.000'
    select * from Orders
    where OrderDate between @D1 and @D2
    GO

     

    *** צרף לנו את המצב המעשי שלך ונוכל לעזור אני מניח למטב את העבודה

    יום חמישי 01 ספטמבר 2011 20:29
    מנחה דיון
  • -

    • הוצע כתשובה על-ידי Assaf_Shalem יום שישי 02 ספטמבר 2011 10:10
    • נערך על-ידי eravuna יום שני 05 ספטמבר 2011 09:51
    יום חמישי 01 ספטמבר 2011 21:53
  • אם הבנתי נכון את הבעיה אז היא לא קשורה למה שהצגת בהסבר (כמובן שיכול להיות שאני לא הבנתי אותו ונחכה לשואל השאלה). מה שאני הבנתי מהשאלה זה שעבור אותם נתונים של סינון השימוש בפרמטרים מייצר תוכנית הרצה שונה מאשר שימוש ישיר (וזה דיי ברור). מדובר על אותו אופן הרצה ואותם נתונים כשכל ההבדל הוא שימוש בפרמטרים או שימוש בערך מפורש.

    למשל 2 השאילתות האלא מייצרות תוכנית הרצה שונה (זו לא דוגמה זהה סתם להמחיש הבדל עם ובלי שימוש בפרמטר), למרות שהן כביכול זהות ובטח שהן זהות מבחינת הסינון תאריכים (באחד פשוט אין שימוש בפרמטר ובשני יש):

    use Northwind
    go

    select * from Orders
    where OrderDate between '1996-07-04 00:00:00.000' and '1996-07-11 00:00:00.000'
    GO

    declare @D1 as datetime = '1996-07-04 00:00:00.000'
    declare @D2 as datetime = '1996-07-11 00:00:00.000'
    select * from Orders
    where OrderDate between @D1 and @D2
    GO

    לא זה מה שהוא שאל?!?

    • סומן כתשובה על-ידי Ami Levin יום שני 05 ספטמבר 2011 12:59
    יום שישי 02 ספטמבר 2011 15:23
    מנחה דיון
  • מומלץ לחפש חומר על
    Google search on SQL Parameter Sniffing
    שבת 03 ספטמבר 2011 17:09
    מנחה דיון
  • תודה לכולם מקרב לב, אתה הבנת בדיוק את כוונתי, אני מכניס לפרמטרים בדיוק את אותם ערכים שבאופציה השניה כתבתי מפורשות. כל הבעיה התחילה כאשר הרצתי INSERT SELECT ענק בלולאה ע"י משתנים וראיתי שהוא לא זז ואז הפסקתי אותו והכרחתי אותו ע"י WITH INDEX .

    הבת שלי עשתה אותו הדבר עם UPDATE וגם שם האינדקס לא פעל בלולאה ובUPDATE הTABLE_HINT הוא LIMITED ואין WITH INDEX והיא נאלצה להפעיל את הלולאה לצורך PRINT שיצר לה 300 משפטי  UPDATE עם תאריכים מפורשים ולהריץ אותם וזה עבד מהר מאוד.

     

    אבל תסכימו איתי שהתופעה הזאת מרגיזה ומתסכלת

     

    במיוחד תודה לך (Pituach) על הבנתך אותי.

    תודה לכולם

    יום שני 05 ספטמבר 2011 08:08
  • תודה על התודה :-)
    יום שני 05 ספטמבר 2011 22:55
    מנחה דיון