none
VIEW וביצועים RRS feed

  • שאלה

  • היי.

    שאלת ביצועים, שחשבתי שאני סגור על התשובה אבל ערערו לי קצת את הבטחון.....

    יש לי VIEW כבד, שמכיל ב-SELECT שלו JOIN בין כמה טבלאות גדולות.

    אני עושה SELECT כלשהו בין ה-VIEW לטבלה נוספת, שמצמצם לי את השורות שה-VIEW אמור להחזיר בצורה ניכרת, ממש לרמה של שורות ספורות (במקום מאות\אלפים\ויותר).

    האם ביצועי ה-VIEW (וכתוצאה מכך סה"כ ביצועי השאילתא הנ"ל) יושפעו מכך שצדובר בשורות ספורות, וה-SQL ידע להריץ את ה-VIEW רק על השורות הרלוונטיות?

    או בניסוח אחר, כללי יותר: האם בהרצה של ה-VIEW הוא רץ בנפרד ואז עושה JOIN ל-SELECT שקרא לו, או שהתוכן שלו "מועתק" לשאילתא ואז האופטימייזר מתחשב בזה כחלק מהשאילתא עצמה?

    מקווה שהייתי ברור.... תודה!


    itaigitt, http://copypastenet.blogspot.com
    יום שלישי 26 אפריל 2011 12:14

תשובות

  • הי,

    על דאגה, מתבצעת העתקה של הקוד מה- view.

    תוכניות הביצוע יהיו זהות, אתה יכול לסמלץ דוגמא בקלות ע"מ להסיר ספק, אני ביצעתי.

    בהצלחה

     

     


    אסף שלם
    • סומן כתשובה על-ידי itaigitt יום רביעי 27 אפריל 2011 08:20
    יום שלישי 26 אפריל 2011 12:39
  • היי.

    התלחתי לסמלץ ולהגיע למסקנה כמו שלך:

    עשיתי שאילתא פשוטה העושה JOIN בין VIEW שמחזיר אלפי שורות לטבלה שמחזירה אלפי שורות, ופלטרתי על הטבלה ככה שבסוף חוזרות 2-3 שורות בלבד.

    ה-EXECUTION PLAN הראתה פנייה לטבלאות של ה-VIEW עצמם ולא ל-VIEW,

    וה-EXECUTION PLAN של השאילתא הזו וה-EXECUTION PLAN של שאילתא אחרת שפירקה את ה-VIEW לתוך השאילתא כטבלאות היו זהות.

    תודה!


    itaigitt, http://copypastenet.blogspot.com
    • סומן כתשובה על-ידי itaigitt יום רביעי 27 אפריל 2011 08:20
    יום רביעי 27 אפריל 2011 08:20
  • הי,

    לצערנו לא יחסך ה- Join אתה יכול לראות ב- execution plan של הדוגמא בפוסט הקודם אך החישוב של c יחסך, תודה לאל.

    חצי נחמה.

     

    תחליף את ה-

    Select c.clientId, client_name, OrderDetails
    from dbo.clients c
    Inner Join dbo.ClientOrders co on co.clientid = c.clientId
    Inner Join #Clients On

    ב-

    Select c.clientId, client_name

    from dbo.clients c
    Inner Join dbo.ClientOrders co on co.clientid = c.clientId
    Inner Join #Clients On

     

     


    אסף שלם
    • סומן כתשובה על-ידי itaigitt יום שני 02 מאי 2011 14:35
    יום שני 02 מאי 2011 14:18

כל התגובות

  • הי,

    על דאגה, מתבצעת העתקה של הקוד מה- view.

    תוכניות הביצוע יהיו זהות, אתה יכול לסמלץ דוגמא בקלות ע"מ להסיר ספק, אני ביצעתי.

    בהצלחה

     

     


    אסף שלם
    • סומן כתשובה על-ידי itaigitt יום רביעי 27 אפריל 2011 08:20
    יום שלישי 26 אפריל 2011 12:39
  • אשמח לראות את הסימלוץ שלך... תודה :-)

    לפי סימלוץ פשוט שעשיתי הבנתי שהקריאה ל-VIEW מתבצעת לפני הקריאה לטבלה.... מה פספסתי?


    itaigitt, http://copypastenet.blogspot.com
    יום שלישי 26 אפריל 2011 13:15
  • היי.

    התלחתי לסמלץ ולהגיע למסקנה כמו שלך:

    עשיתי שאילתא פשוטה העושה JOIN בין VIEW שמחזיר אלפי שורות לטבלה שמחזירה אלפי שורות, ופלטרתי על הטבלה ככה שבסוף חוזרות 2-3 שורות בלבד.

    ה-EXECUTION PLAN הראתה פנייה לטבלאות של ה-VIEW עצמם ולא ל-VIEW,

    וה-EXECUTION PLAN של השאילתא הזו וה-EXECUTION PLAN של שאילתא אחרת שפירקה את ה-VIEW לתוך השאילתא כטבלאות היו זהות.

    תודה!


    itaigitt, http://copypastenet.blogspot.com
    • סומן כתשובה על-ידי itaigitt יום רביעי 27 אפריל 2011 08:20
    יום רביעי 27 אפריל 2011 08:20
  • הי איתי,

    אני יצרף את הניסוי שלי מאוחר יותר, אני קצת לחוץ כרגע, ע"מ להשלים את הפוסט.

    ביי בינתיים ויום טוב


    אסף שלם
    יום רביעי 27 אפריל 2011 09:27
  • הי,

    הקוד מצורף.

    יצרתי טבלת לקוחות והזמנות -לקוחות 100000 הזמנות 400000.

    יצרתי View שמאחד את שתי הטבלאות.

    הרצתי שאילתה שמביא הזמנות של שתי לקוחות ע"י join לטבלה זמנית.

    ה- plan זהה בפניה ל- View כמו גם בפניה ישירה לטבלאות.

    בהצלחה

    תמחק את ה- use בראש הסקריפט 

     

     

    use db_dba
    Go
    set nocount on 
    
    Create table dbo.clients
    (
    	ClientId	int not null Constraint PK_clients_ClientId primary key,
    	Client_Name char(50) 
    )
    Go
    
    Create table dbo.ClientOrders
    (
    	OrderId		int not null identity(1,1) Constraint PK_ClientOrders_OrderId primary key,
    	ClientId	int not null,
    	OrderDetails xml 
    )
    Go
    Create nonclustered index idx_ClientOrders_nc_ClientId on dbo.ClientOrders (ClientId)
    Go
    -- Insert 100,000 clients
    Declare @Counter int
    Set @Counter = 1
    While @Counter <= 100000
    begin
    	insert dbo.clients (ClientId, Client_Name)
    	Select @Counter, 'Client name'
    	
    	Set @Counter = @Counter + 1
    End
    
    -- add 4 orders for each client
    Insert dbo.ClientOrders (ClientId, OrderDetails)
    Select ClientId, ordDetails
    From dbo.clients
    Cross apply 
    (
    	Select '<OrderDetails id="1"><order>Item1</order><order>Item2</order><order>Item3</order><order>Item4</order><order>Item5</order></OrderDetails>' As ordDetails union all
    	Select '<OrderDetails id="2"><order>Item1</order><order>Item2</order><order>Item3</order><order>Item4</order><order>Item5</order></OrderDetails>' As ordDetails union all
    	Select '<OrderDetails id="3"><order>Item1</order><order>Item2</order><order>Item3</order><order>Item4</order><order>Item5</order></OrderDetails>' As ordDetails union all
    	Select '<OrderDetails id="4"><order>Item1</order><order>Item2</order><order>Item3</order><order>Item4</order><order>Item5</order></OrderDetails>' As ordDetails 
    ) OrderDetails
    Go
    
    Create view dbo.vw_ClientOrders
    As
    
    Select c.clientId, client_name, OrderDetails
    from dbo.clients c
    Inner Join dbo.ClientOrders co on co.clientid = c.clientId 
    
    Go
    
    Create table #Clients (CltId int)
    Insert #Clients values (10100)
    Insert #Clients values (70200)
    
    -- Get data using view
    Select clientId, client_name, OrderDetails
    from dbo.vw_ClientOrders co
    Inner Join #Clients On CltId = clientId
    
    
    -- Get data by referencing the tables
    Select c.clientId, client_name, OrderDetails
    from dbo.clients c
    Inner Join dbo.ClientOrders co on co.clientid = c.clientId 
    Inner Join #Clients On CltId = c.clientId
    

    אסף שלם
    יום רביעי 27 אפריל 2011 11:56
  • היי.

    שאלה נוספת באותו הקשר:

    נאמר שיש לי VIEW שמחזיר שלושה שדות: a,b,c.

    כאשר אני מריץ:

    select a, b from VIEW

    האם האופטימייזר יידע לא לחשב את c?

    כלומר - האם זה יחסוך את ה-JOIN לטבלה נוספת שמביאה את c, או במקרה הגרוע יותר (שלצערי זה המקרה שלי....) יחסוך את החישוב שמחשב את c?


    itaigitt, http://copypastenet.blogspot.com
    יום שני 02 מאי 2011 13:48
  • הי,

    לצערנו לא יחסך ה- Join אתה יכול לראות ב- execution plan של הדוגמא בפוסט הקודם אך החישוב של c יחסך, תודה לאל.

    חצי נחמה.

     

    תחליף את ה-

    Select c.clientId, client_name, OrderDetails
    from dbo.clients c
    Inner Join dbo.ClientOrders co on co.clientid = c.clientId
    Inner Join #Clients On

    ב-

    Select c.clientId, client_name

    from dbo.clients c
    Inner Join dbo.ClientOrders co on co.clientid = c.clientId
    Inner Join #Clients On

     

     


    אסף שלם
    • סומן כתשובה על-ידי itaigitt יום שני 02 מאי 2011 14:35
    יום שני 02 מאי 2011 14:18
  • כלומר עם c מחושב נגיד ע"י פונקציה או סתם חישוב SQL-י מורכב מכמב טבלאות הוא לא יתבצע?????

    אם כן - הפתעת אותי... וגם מיקרוסופט :-)


    itaigitt, http://copypastenet.blogspot.com
    יום שני 02 מאי 2011 14:25
  • הי,

    C לא יחושב, במידה והוא לא מופיע ב- Select Columns.

    אתה בקלות יכול לוודא את זה ב- execution plan.

    צריך עזרה?


    אסף שלם
    יום שני 02 מאי 2011 14:29
  • אני חושב שהבנתי, אני אאמת את זה מול המקרה שלי במדויק ואעלה לפוסט תובנות נוספות או שאלות נוספות.

    תודה!


    itaigitt, http://copypastenet.blogspot.com
    יום שני 02 מאי 2011 14:35