none
sql plan RRS feed

  • שאלה

  • :קצת קשה לנסח את השאלה אבח אני אנסה 

    : נתונה השאילתה הבאה

    Select

    PaymentTerminal.id,Prm_Users.name,PaymentTerminal.RequestDate,PaymentTerminal.RequestSum,PaymentTerminal.currency,PaymentTerminal.Status,PaymentTerminal.ServiceType,PaymentTerminal.ProcessSum

     

    from PaymentTerminal inner join Prm_Users on PaymentTerminal.RequestTeleId = Prm_Users.id

     

    where PaymentTerminal.RequestDate >= GETDATE() -5 and

    PaymentTerminal

    .RequestDate < GETDATE() and --DATEADD(day,1,'''+@date1x+''') and
     

    PaymentTerminal

    .Status in (8) and RequestLoc in (1,6,7,2)

    עכשיו  הנתונים על הטבלאות:

      RequestTeleId  ואינדקס על עמודת  RequestDate כוללת קלסתר אינדקס על עמודת payment terminal טבלת

      מכילה  אינדקס על   prm_user   טבלת 

    id ווקלסתר אינדקס על עמודת   name   עמודה מסוג

      מייצר  sql  שימו לב  לתוכנית הפעולה ש

     

    |

    --Hash Match(Inner Join, HASH:([usagc].[dbo].[PaymentTerminal].[RequestTeleId])=([usagc].[dbo].[Prm_Users].[id]))

     

    |

    --Clustered Index Seek(OBJECT:([usagc].[dbo].[PaymentTerminal].[Cldate]), SEEK:([usagc].[dbo].[PaymentTerminal].[RequestDate]

     

    -- >= getdate()-'1900-01-06 00:00:00.000' AND [usagc].[dbo].[PaymentTerminal].[RequestDate] < getdate()), WHERE:([usagc].[dbo].[PaymentTerminal].[Status]=(8)

     

    -- AND ([usagc].[dbo].[PaymentTerminal].[RequestLoc]=(1) OR [usagc].[dbo].[PaymentTerminal].[RequestLoc]=(2) OR [usagc].[dbo].[PaymentTerminal].[RequestLoc]=(6)

     

    -- OR [usagc].[dbo].[PaymentTerminal].[RequestLoc]=(7))) ORDERED FORWARD)

     

    |

    --Index Scan(OBJECT:([usagc].[dbo].[Prm_Users].[IX_name]))

    name  השורה האחרונה היא הבעייתי מדוע הוא בוחר להשתמש ב אינדקס שקיים על עמודת ה

    id כאשר קיים קלסתר אינדקס על עמודת ה   prm user מטבלת    

    . ורק אז להביא רת הנתונים Hash Match   ולבצע

    וגורם  ומכריח אותו להשתמש ב בקלסתר אינדקס כלומר השאילתה תיראה כך  hint   אם אני שם

    set

     

    statistics io

    on

    --SET SHOWPLAN_TEXT ON

    Select

     

    PaymentTerminal.id,Prm_Users.name,PaymentTerminal.RequestDate,PaymentTerminal.RequestSum,PaymentTerminal.currency,PaymentTerminal.Status,PaymentTerminal.ServiceType,PaymentTerminal.

    ProcessSum

     

    from PaymentTerminal inner join Prm_Users with (index(PK_prmid )) on PaymentTerminal.RequestTeleId = Prm_Users.

    id

     

    where PaymentTerminal.RequestDate >= GETDATE() -5 and

    PaymentTerminal

    .RequestDate < GETDATE() and

    --DATEADD(day,1,'''+@date1x+''') and

    PaymentTerminal

    .Status in (8) and RequestLoc in (1,6,7,2

    )

      

      עכשיו תוכנית הפעולה נראית נהדר:

     

    |--Merge Join(Inner Join, MERGE:([usagc].[dbo].[Prm_Users].[id])=([usagc].[dbo].[PaymentTerminal].[RequestTeleId]), RESIDUAL:([usagc].[dbo].[Prm_Users].[id]=[usagc].[dbo].[PaymentTerminal].[RequestTeleId]))
     

     

    |--Clustered Index Scan(OBJECT:([usagc].[dbo].[Prm_Users].[PK_prmid]), ORDERED FORWARD)
     

     

    |--Sort(ORDER BY:([usagc].[dbo].[PaymentTerminal].[RequestTeleId] ASC))
     

     

    |--Clustered Index Seek(OBJECT:([usagc].[dbo].[PaymentTerminal].[Cldate]), SEEK:([usagc].[dbo].[PaymentTerminal].[RequestDate]
     

     

    -- >= getdate()-'1900-01-06 00:00:00.000' AND [usagc].[dbo].[PaymentTerminal].[RequestDate] < getdate()), WHERE:([usagc].[dbo].[PaymentTerminal].[Status]=(8)
     

     

    -- AND ([usagc].[dbo].[PaymentTerminal].[RequestLoc]=(1) OR [usagc].[dbo].[PaymentTerminal].[RequestLoc]=(2) OR [usagc].[dbo].[PaymentTerminal].[RequestLoc]=(6)
     

     

    -- OR [usagc].[dbo].[PaymentTerminal].[RequestLoc]=(7))) ORDERED FORWARD)

    עכשיו תוכנית הפעולה נראית נהדר

     

    . ןזה לא מתבצע כברירת מחדל של המערכת

    payment terminal נתונים  טבלת

                                        name rows reserved data index_size unused
    PaymentTerminal 38396       14304 KB 12808 KB 1328 KB 168 KB

    : prm_user  נתוני טבלת

                                          name rows reserved data index_size unused
    Prm_Users 1800        1184 KB 328 KB 192 KB 664 KB

     אני מקווה שלא חפרתי יותר מדי :)

    ושהייתי מספיק ברור

    תודה מראש שרון

     

     

     

    hint הבעיה שלי היא מדוע אני צריך לתת 
    יום שני 04 יולי 2011 13:35

תשובות

  • הי שרון,

    אני לא רואה סיבה למה הוא צריך להשתמש ב- index על ה- user?

    ע"פ השאילתא מה שהוא צריך מטבלת users זה רק:

    1.User Id עבור ה- Join.

    2. name עבור ה- result set.

    מכוון שיש nonclustered index על name שמכיל בתוכו את ה- User Id,עקב היותו ה- Clustered key אזי ע"י שימוש ב- index הוא "משלים" את המשימה.

    מה שנקרא covered index.

    אני מקוה שזה ברור ולא החסרתי פרטים.

    עןד סיבות להיא שימוש ב- Index:

    1. סטטיסטיקות לא מעודכנות.

    2. חוסר סלקטיביות.

    3. טבלה "קטנה", עדיף לבצע scan במקום Seek + lookup.

    4. האינדקס disable.

    לדעתי במקרה שלך התוכניתהמקורית טובה יותר מזו של ה- hint מכוון שיש שימוש באינדקס בלבד ללא צורך בפניות לטבלה.

    יום טוב,


    אסף שלם
    • הוצע כתשובה על-ידי pituachMVP, Editor יום חמישי 07 יולי 2011 09:22
    • סומן כתשובה על-ידי Meir Pinto יום ראשון 10 יולי 2011 10:43
    יום שני 04 יולי 2011 21:27

כל התגובות

  • הי שרון,

    אני לא רואה סיבה למה הוא צריך להשתמש ב- index על ה- user?

    ע"פ השאילתא מה שהוא צריך מטבלת users זה רק:

    1.User Id עבור ה- Join.

    2. name עבור ה- result set.

    מכוון שיש nonclustered index על name שמכיל בתוכו את ה- User Id,עקב היותו ה- Clustered key אזי ע"י שימוש ב- index הוא "משלים" את המשימה.

    מה שנקרא covered index.

    אני מקוה שזה ברור ולא החסרתי פרטים.

    עןד סיבות להיא שימוש ב- Index:

    1. סטטיסטיקות לא מעודכנות.

    2. חוסר סלקטיביות.

    3. טבלה "קטנה", עדיף לבצע scan במקום Seek + lookup.

    4. האינדקס disable.

    לדעתי במקרה שלך התוכניתהמקורית טובה יותר מזו של ה- hint מכוון שיש שימוש באינדקס בלבד ללא צורך בפניות לטבלה.

    יום טוב,


    אסף שלם
    • הוצע כתשובה על-ידי pituachMVP, Editor יום חמישי 07 יולי 2011 09:22
    • סומן כתשובה על-ידי Meir Pinto יום ראשון 10 יולי 2011 10:43
    יום שני 04 יולי 2011 21:27
  •  תודה על התגובה  ותודה על הספר :)

    יום חמישי 07 יולי 2011 09:03