none
sql operator and execution plan RRS feed

  • שאלה

  • היי,

    השאלה שלי  היא כזאת :

    שאני מייצר שאילתה ושם תנאים  של end   או or    איך  exection plan  של SQL יודע  לפי איזה סדר לבצע אותם ?

    אני שואל בגלל  שהייתה לי שאילתה שהביצועים שלה השתפרו פלאים לאחר ששיניתי את מיקום האופרטור  בשאילתה ב where. ( כמובן ש exection plan השתנה והשאילה יותר יעילה)

     האם יכול להיות ש exection plan   לא מבצע את השאילתה בצורה המיטבית ביותר  בגלל מיקום  האופרטור   ?

    שרון

    יום חמישי 05 אפריל 2012 14:31

תשובות

  • הי שרון,

    קודם כל, במקרה שלך אין לך בכלל OR בשאילתא, חוץ ממקום אחד שנמצא בתוך סוגריים, אז המקרה יותר קל. מדובר באוסף של תנאים שמחוברים ב-AND ביניהם.

    לא מזמן כתבתי פוסט על אופטימיזציה של שאילתות שמשתמשות ב-AND וב-OR. אתה מוזמן לקרוא: http://www.madeira.co.il/and-vs-or/.

    באופן כללי, כמו שאתה מניח, סדר התנאים הלוגיים בתוך ה-WHERE, כל עוד כולם מחוברים ביניהם ב-AND, לא אמור להשפיע על ה-Execution Plan. ה-Optimizer אמור להיות מספיק חכם בשביל לסדר את השאילתא בצורה האופטימלית בלי קשר לטקסט המקורי של השאילתא. אבל שים לב שכתבתי פעמיים "אמור". כשהשאילתא פשוטה יחסית, אין ל-Optimizer שום בעיה להתמודד עם סדר התנאים, ובלי קשר לסדר שבו כתבת אותם, תקבל תמיד את אותו Execution Plan.

    אבל כבר נתקלתי כמה פעמים בעבר בסיטואציה דומה לשלך, כאשר השאילתא מאוד מורכבת ומכילה הרבה תנאים שונים ומשונים, ואז ה-Optimizer לא מצליח להתמודד ולהגיע לאותו Execution Plan בכל סידור של התנאים. הנה דוגמא: http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=45836. זה לא אמור לקרות, אבל אני גם לא חושב שאפשר לקרוא לזה באג. תחשוב על זה... ככל שמספר התנאים ב-WHERE עולה, מספר הקומבינציות לסדר אותם עולה אקספוננציאלית. בשלב כלשהו, ה-Optimizer חייב לעשות הנחות ולקצר תהליכים, אחרת תהליך האופטימיזציה ימשך לנצח. במקרים האלה תהיה משמעות לסדר הכתיבה של התנאים ב-WHERE.

    בדרך-כלל, הפתרון הוא לפשט את השאילתא. מנסיוני, ברוב המקרים בהם נתקלתי בשאילתא מאוד מורכבת, היא לא באמת היתה צריכה להיות מורכבת. אחרי קצת אופטימיזציה, אפשר לפשט את השאילתא לרמה שאיתה ה-Optimizer יכול להתמודד בכבוד. זה גם המקרה שלך, לדעתי. אני אתן לך שתי דוגמאות:

    1. יש לך שלושה תנאים רצופים על da.Date, שלדעתי אפשר לשכתב אותם באופן הבא: da.Date > '2008-01-01' AND da.Date < '2010-12-30'

    2. בשני מקומות אתה משתמש בתנאי על העמודה da.Phone. בשניהם התנאי מופיע פעמיים. זה אותו תנאי בדיוק. ההבדל היחיד הוא שפעם אחת שם העמודה הוא da.phone ובפעם השניה הוא da.Phone. בהנחה שאתה לא משתמש ב-Case Sensitive Collation, אין שום הבדל בין התנאים, ואפשר לאחד ביניהם.

    יש עוד דברים שאפשר לעשות כדי לפשט ולייעל את השאילתא. אני מניח שאחרי שתפשט אותה, היא תהיה מספיק פשוטה כדי שסדר הכתיבה לא ישפיע על בחירת ה-Execution Plan, מפני שה-Optimizer כבר יוכל להתמודד איתה בכבוד.

    בהצלחה!

    גיא גלנצר

    יועץ ומדריך SQL Server

    Madeira - SQL Server Services

    http://www.madeira.co.il/

    • הוצע כתשובה על-ידי Assaf_Shalem יום שני 09 אפריל 2012 10:37
    • סומן כתשובה על-ידי sharonof יום שני 16 אפריל 2012 07:16
    יום שני 09 אפריל 2012 09:30
    מנחה דיון
  • DBCC FREEPROCCACHE 
    DBCC DROPCLEANBUFFERS
    set statistics io on
    select   dt.id,da.[status] from    dtcc dt with (nolock)
    inner join  dacc da with (nolock) on da.Id=dt.UserID 
    where 
    da.El = 1 and 
    da.Fr=1
    and da.IsP=0   and
    (
    	da.Date < DATEADD(d,0,convert(smalldatetime,convert(char(10), '2010-12-30', 102)))
    	and 
    	da.Date > DATEADD(d,0,convert(smalldatetime,convert(char(10), '2008-01-01', 102)))
    	and
    	'2012-04-06 00:00:00.000'   
    	>
    	da.Date  
    	and   dt.[St]  in (select Value from Split ('1,2,5,21,22',',') as dt)
    	and    
    	dt.loc is null  
    	 and not 
    	 (  
    	 REPLACE( replace(replace(da.phone,' ',''),'+',''),'0','') like '98%' and REPLACE( replace(replace(da.Phone,' ',''),'+',''),'0','') like '98%' 
    	 )     
    )
    and 
    ( 
    len(replace(da.phone,' ','')) between 6 and 20  OR  len(replace(da.Phone,' ','')) between 6 and 20
    )  
    and
    dt.St <> 4 and dt.St <>25 and da.St<>1000  and (select count (id) from tl with (nolock) where user_id  = da.Id and active = 1) =0
    and 
    (da.UpdaterName is null or da.UpdaterName = '' )
    and da.[Status]  in (select Value  from Split ('600',',') as da) 

    ככה :

    השאילתה הזאת כמו שהיא ככה לוקחת שעות -- אם אני לוקח את השורה האחרונה  ומעביר אותה  אותה לאחרי השורה da.fr=1

    אז היא עובדת בשניות   לאחר בדיקות הסוגריים הלוגיקה  של השאילתה לא משתנה , ( תקנו אותי אם אני טועה :))  אבל  תוכנית העבודה של SQL בהחלט משתנה  והיא הרבה יותר מהירה.

     split - פונקציה שמקבלת מערך  מחרוזת מופרד בפסיקים ומחזירה ערכים מופרדים . (table value function)

    הטבלאות מאונדקסות כראוי למיטה הבנתי.

    כמה מסקנות שהגעתי אליהם :

    לאחר בדיקה שמתי לב  שתוכנית תהיה מהירה הרבה  יותר אם אני לא אשתמש בפונקציית ה split   כלומר אם אני משתנה או קבוע המנוע משתמש באינדקס שיש על טבלת da על עמודת

      status   אבל אין לי ברירה אני חייב לחפש כמה ערכים  ולא רק ערך אחד אז חייב להשתמש ב split.

    השאלה שלי היא :

    מדוע מיקום  של המשפט האחרון  משפיע  על על  exction plan -  מה ששמתי לב  בעת שינוי מ המיקום של משפט האחרון     לאחר משפט זה  da.fr=1 שתוכנית הפעולה משתנה -- כתוצאה מזה  פילטור הנתונים

    הרבה יותר יעיל מהיר  והשאילה מתיימת הרבה יותר מהיר  -- SQL קודם  בודק את התנאי הזה באמצעות join לטבלת הsplit   הוא בודק  :

    ( da.st in ( select 600 from split   ואז ממשיך הלאה .

    כאשר השאילה כמו שהיא במצבה המקורי  SQL עושה את כל הפעולות ורק בסוף מבצע  ( da.st in ( select 600 from split  

    וזה  גורם לשאילתה לקחת המון זמן.

    אשמח לשמוע רעינות או תובנות שלכם למצב הנ"ל

    תודה שרון עופר

    • סומן כתשובה על-ידי sharonof יום שני 16 אפריל 2012 07:16
    יום ראשון 08 אפריל 2012 10:22
  • אני יכול רק לנחש שהמערכת אינה יכולה "לחשב" כמה עולה השינוש בפונקציה SPLIT ולכן מעריכה את העלויות לא נכון ומשתמשת בה לא בחוכמה (סביר שהיא תפעיל קודם את התנאים היותר מפלטרים, סלקטיביים).

    מנסיון במקום עבודתי- הפונקציה הזו מאוד יקרה מבחינת ביצועים, למרות שהיא הכי יעילה מבחינת האפשרויות לביצוע SPLIT, וניתן לוותר על השימוש בה כך שהקוד יהיה הרבה יותר יעיל.
    לדוגמה כיצד עיין כאן- http://blogs.microsoft.co.il/blogs/gerireshef/archive/2011/08/24/GR20110824.aspx
    (
    לאחר המשפט המחיל ב"כפי שאפשר להבחין").


    Geri Reshef http://gerireshef.wordpress.com

    • סומן כתשובה על-ידי sharonof יום שני 16 אפריל 2012 07:16
    יום ראשון 08 אפריל 2012 12:35
  • פיתוח שלום,

    לא כל כך הבנתי מה  אתה מעוניין שאני אצרף ...

    זה פקודת dml ואין פה פקודת ddl

    אשמח אם תסביר לי איך אתה יכול לעזור לי :)

    שרון.

    • סומן כתשובה על-ידי sharonof יום שני 16 אפריל 2012 07:16
    יום ראשון 08 אפריל 2012 18:46
  • השאילתה שלך רצה על נתונים ממסד הנתונים שלך?
    אם כן יש שימוש בטבלאות

    אנחנו לא יכולים להריץ את השאילתה כמובן בלי לקבל שגיאה.

    השימוש ב: from dtcc וכן inner join  dacc מצביע על כך שיש לך DDL כמובן.

    DDL ייתן לנו את הטבלאות/אלמנטים הרלוונטיים ו DML ייתן לנו כמה רשומות לדוגמה ואז נוכל להריץ את השאילתה ולראות את תוכנית ההרצה אצלנו

    נראה לי שהקישור הבא מאוד מומלץ כרגע כדי לענות על העניין ולהבהיר מה אנחנו צריכים תמיד ולמה


    signature

    • סומן כתשובה על-ידי sharonof יום שני 16 אפריל 2012 07:16
    יום שני 09 אפריל 2012 05:26
    מנחה דיון
  • אני חושב שענית לבד על השאלה אם כל התנאים הם AND אז ה SQL מבצע אותם לפי הסדר.

    אם אני הייתי כותב אופטימיזציה אוטומטית ל WHERE אז הייתי שם את האופרטור של SPLIT ו SELECT בעדיפות נמוכה מאשר פרמטרים סטאטים כך שמה שהוא עושה זה הגיוני.

    אם בביצועים עסקינן אז:

    א. הייתי מעביר את השאילטה ל SP

    ב. מבצע הכפלת שדות או מוודא בקוד ההזנה שאיני לא אצטרך להשתמש בפונקציית replace עבור כל שליפה אלה רק פעם אחת בהזנה.

    ג. לגביי ה SPLIT יוצר טבלה זמנית ואז inner join איתה

    ד. אינקסים כמובן

    • סומן כתשובה על-ידי sharonof יום שני 16 אפריל 2012 07:16
    יום שני 09 אפריל 2012 07:13
  • פיתוח תודה על התשובה -

    אני אנסה לעשות זאת  -- יש רק בעיה קטנה :

    שיש לי בעיה לחשוף את שמות הטבלאות והשדות   באינטרנט

    שרון

    • סומן כתשובה על-ידי sharonof יום שני 16 אפריל 2012 07:16
    יום שני 09 אפריל 2012 09:20
  • גרי תודה,

    אני  יעיין בזה.

    • סומן כתשובה על-ידי sharonof יום שני 16 אפריל 2012 07:16
    יום שני 09 אפריל 2012 09:22

כל התגובות

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

    Geri Reshef http://gerireshef.wordpress.com

    יום חמישי 05 אפריל 2012 18:32
  • DBCC FREEPROCCACHE 
    DBCC DROPCLEANBUFFERS
    set statistics io on
    select   dt.id,da.[status] from    dtcc dt with (nolock)
    inner join  dacc da with (nolock) on da.Id=dt.UserID 
    where 
    da.El = 1 and 
    da.Fr=1
    and da.IsP=0   and
    (
    	da.Date < DATEADD(d,0,convert(smalldatetime,convert(char(10), '2010-12-30', 102)))
    	and 
    	da.Date > DATEADD(d,0,convert(smalldatetime,convert(char(10), '2008-01-01', 102)))
    	and
    	'2012-04-06 00:00:00.000'   
    	>
    	da.Date  
    	and   dt.[St]  in (select Value from Split ('1,2,5,21,22',',') as dt)
    	and    
    	dt.loc is null  
    	 and not 
    	 (  
    	 REPLACE( replace(replace(da.phone,' ',''),'+',''),'0','') like '98%' and REPLACE( replace(replace(da.Phone,' ',''),'+',''),'0','') like '98%' 
    	 )     
    )
    and 
    ( 
    len(replace(da.phone,' ','')) between 6 and 20  OR  len(replace(da.Phone,' ','')) between 6 and 20
    )  
    and
    dt.St <> 4 and dt.St <>25 and da.St<>1000  and (select count (id) from tl with (nolock) where user_id  = da.Id and active = 1) =0
    and 
    (da.UpdaterName is null or da.UpdaterName = '' )
    and da.[Status]  in (select Value  from Split ('600',',') as da) 

    ככה :

    השאילתה הזאת כמו שהיא ככה לוקחת שעות -- אם אני לוקח את השורה האחרונה  ומעביר אותה  אותה לאחרי השורה da.fr=1

    אז היא עובדת בשניות   לאחר בדיקות הסוגריים הלוגיקה  של השאילתה לא משתנה , ( תקנו אותי אם אני טועה :))  אבל  תוכנית העבודה של SQL בהחלט משתנה  והיא הרבה יותר מהירה.

     split - פונקציה שמקבלת מערך  מחרוזת מופרד בפסיקים ומחזירה ערכים מופרדים . (table value function)

    הטבלאות מאונדקסות כראוי למיטה הבנתי.

    כמה מסקנות שהגעתי אליהם :

    לאחר בדיקה שמתי לב  שתוכנית תהיה מהירה הרבה  יותר אם אני לא אשתמש בפונקציית ה split   כלומר אם אני משתנה או קבוע המנוע משתמש באינדקס שיש על טבלת da על עמודת

      status   אבל אין לי ברירה אני חייב לחפש כמה ערכים  ולא רק ערך אחד אז חייב להשתמש ב split.

    השאלה שלי היא :

    מדוע מיקום  של המשפט האחרון  משפיע  על על  exction plan -  מה ששמתי לב  בעת שינוי מ המיקום של משפט האחרון     לאחר משפט זה  da.fr=1 שתוכנית הפעולה משתנה -- כתוצאה מזה  פילטור הנתונים

    הרבה יותר יעיל מהיר  והשאילה מתיימת הרבה יותר מהיר  -- SQL קודם  בודק את התנאי הזה באמצעות join לטבלת הsplit   הוא בודק  :

    ( da.st in ( select 600 from split   ואז ממשיך הלאה .

    כאשר השאילה כמו שהיא במצבה המקורי  SQL עושה את כל הפעולות ורק בסוף מבצע  ( da.st in ( select 600 from split  

    וזה  גורם לשאילתה לקחת המון זמן.

    אשמח לשמוע רעינות או תובנות שלכם למצב הנ"ל

    תודה שרון עופר

    • סומן כתשובה על-ידי sharonof יום שני 16 אפריל 2012 07:16
    יום ראשון 08 אפריל 2012 10:22
  • אני יכול רק לנחש שהמערכת אינה יכולה "לחשב" כמה עולה השינוש בפונקציה SPLIT ולכן מעריכה את העלויות לא נכון ומשתמשת בה לא בחוכמה (סביר שהיא תפעיל קודם את התנאים היותר מפלטרים, סלקטיביים).

    מנסיון במקום עבודתי- הפונקציה הזו מאוד יקרה מבחינת ביצועים, למרות שהיא הכי יעילה מבחינת האפשרויות לביצוע SPLIT, וניתן לוותר על השימוש בה כך שהקוד יהיה הרבה יותר יעיל.
    לדוגמה כיצד עיין כאן- http://blogs.microsoft.co.il/blogs/gerireshef/archive/2011/08/24/GR20110824.aspx
    (
    לאחר המשפט המחיל ב"כפי שאפשר להבחין").


    Geri Reshef http://gerireshef.wordpress.com

    • סומן כתשובה על-ידי sharonof יום שני 16 אפריל 2012 07:16
    יום ראשון 08 אפריל 2012 12:35
  • DDL+DML יכולים לעזור לנו לראות את הדברים שרון ולעזור בצורה יעילה יותר

    signature

    יום ראשון 08 אפריל 2012 18:29
    מנחה דיון
  • פיתוח שלום,

    לא כל כך הבנתי מה  אתה מעוניין שאני אצרף ...

    זה פקודת dml ואין פה פקודת ddl

    אשמח אם תסביר לי איך אתה יכול לעזור לי :)

    שרון.

    • סומן כתשובה על-ידי sharonof יום שני 16 אפריל 2012 07:16
    יום ראשון 08 אפריל 2012 18:46
  • השאילתה שלך רצה על נתונים ממסד הנתונים שלך?
    אם כן יש שימוש בטבלאות

    אנחנו לא יכולים להריץ את השאילתה כמובן בלי לקבל שגיאה.

    השימוש ב: from dtcc וכן inner join  dacc מצביע על כך שיש לך DDL כמובן.

    DDL ייתן לנו את הטבלאות/אלמנטים הרלוונטיים ו DML ייתן לנו כמה רשומות לדוגמה ואז נוכל להריץ את השאילתה ולראות את תוכנית ההרצה אצלנו

    נראה לי שהקישור הבא מאוד מומלץ כרגע כדי לענות על העניין ולהבהיר מה אנחנו צריכים תמיד ולמה


    signature

    • סומן כתשובה על-ידי sharonof יום שני 16 אפריל 2012 07:16
    יום שני 09 אפריל 2012 05:26
    מנחה דיון
  • אני חושב שענית לבד על השאלה אם כל התנאים הם AND אז ה SQL מבצע אותם לפי הסדר.

    אם אני הייתי כותב אופטימיזציה אוטומטית ל WHERE אז הייתי שם את האופרטור של SPLIT ו SELECT בעדיפות נמוכה מאשר פרמטרים סטאטים כך שמה שהוא עושה זה הגיוני.

    אם בביצועים עסקינן אז:

    א. הייתי מעביר את השאילטה ל SP

    ב. מבצע הכפלת שדות או מוודא בקוד ההזנה שאיני לא אצטרך להשתמש בפונקציית replace עבור כל שליפה אלה רק פעם אחת בהזנה.

    ג. לגביי ה SPLIT יוצר טבלה זמנית ואז inner join איתה

    ד. אינקסים כמובן

    • סומן כתשובה על-ידי sharonof יום שני 16 אפריל 2012 07:16
    יום שני 09 אפריל 2012 07:13
  •  היי  ותודה על התגובה .

    א) אז ככה זה אכן רץ  בפרצדורה.

    ב) replace  לא משפיע   על הביצועים בהתייחס לבעיה שהצפתי :)

    ג) לצור טבלה זמנית לא עוזר כי עדיין SQL יבצע את בjoin  עם הטבלה הזמנית בסוף תוכנית העבודה -- ככה שלא השתנה שום דבר מבחינת ביצועים. ( אם יבצע בסוף את ה join  לטבלה זאת)

       בדקתי את זה  בשטח :)

    ד)  הסריקות על הטבלאות הם בעמצעות index seek .

    תודה על הרעיוניות אבל שים לב  למהות של השאלה :

    קח את השורה הזאת :and da.[Status]  in (select Value  from Split ('600',',') as da)

    שים אותם אחרי השורה הזאת :

    da.Fr=1
     ואז  תוכנית העבודה נהיית הרבה יותר יעילה כי הפילטור הראשוני   הזה הרבה יותר יעיל

    and da.[Status]  in (select Value  from Split ('600',',') as da)

    תודה אשמח לשמוע עוד הצעות :)

    שרון

     

    יום שני 09 אפריל 2012 09:13
  • פיתוח תודה על התשובה -

    אני אנסה לעשות זאת  -- יש רק בעיה קטנה :

    שיש לי בעיה לחשוף את שמות הטבלאות והשדות   באינטרנט

    שרון

    • סומן כתשובה על-ידי sharonof יום שני 16 אפריל 2012 07:16
    יום שני 09 אפריל 2012 09:20
  • גרי תודה,

    אני  יעיין בזה.

    • סומן כתשובה על-ידי sharonof יום שני 16 אפריל 2012 07:16
    יום שני 09 אפריל 2012 09:22
  • הי שרון,

    קודם כל, במקרה שלך אין לך בכלל OR בשאילתא, חוץ ממקום אחד שנמצא בתוך סוגריים, אז המקרה יותר קל. מדובר באוסף של תנאים שמחוברים ב-AND ביניהם.

    לא מזמן כתבתי פוסט על אופטימיזציה של שאילתות שמשתמשות ב-AND וב-OR. אתה מוזמן לקרוא: http://www.madeira.co.il/and-vs-or/.

    באופן כללי, כמו שאתה מניח, סדר התנאים הלוגיים בתוך ה-WHERE, כל עוד כולם מחוברים ביניהם ב-AND, לא אמור להשפיע על ה-Execution Plan. ה-Optimizer אמור להיות מספיק חכם בשביל לסדר את השאילתא בצורה האופטימלית בלי קשר לטקסט המקורי של השאילתא. אבל שים לב שכתבתי פעמיים "אמור". כשהשאילתא פשוטה יחסית, אין ל-Optimizer שום בעיה להתמודד עם סדר התנאים, ובלי קשר לסדר שבו כתבת אותם, תקבל תמיד את אותו Execution Plan.

    אבל כבר נתקלתי כמה פעמים בעבר בסיטואציה דומה לשלך, כאשר השאילתא מאוד מורכבת ומכילה הרבה תנאים שונים ומשונים, ואז ה-Optimizer לא מצליח להתמודד ולהגיע לאותו Execution Plan בכל סידור של התנאים. הנה דוגמא: http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=45836. זה לא אמור לקרות, אבל אני גם לא חושב שאפשר לקרוא לזה באג. תחשוב על זה... ככל שמספר התנאים ב-WHERE עולה, מספר הקומבינציות לסדר אותם עולה אקספוננציאלית. בשלב כלשהו, ה-Optimizer חייב לעשות הנחות ולקצר תהליכים, אחרת תהליך האופטימיזציה ימשך לנצח. במקרים האלה תהיה משמעות לסדר הכתיבה של התנאים ב-WHERE.

    בדרך-כלל, הפתרון הוא לפשט את השאילתא. מנסיוני, ברוב המקרים בהם נתקלתי בשאילתא מאוד מורכבת, היא לא באמת היתה צריכה להיות מורכבת. אחרי קצת אופטימיזציה, אפשר לפשט את השאילתא לרמה שאיתה ה-Optimizer יכול להתמודד בכבוד. זה גם המקרה שלך, לדעתי. אני אתן לך שתי דוגמאות:

    1. יש לך שלושה תנאים רצופים על da.Date, שלדעתי אפשר לשכתב אותם באופן הבא: da.Date > '2008-01-01' AND da.Date < '2010-12-30'

    2. בשני מקומות אתה משתמש בתנאי על העמודה da.Phone. בשניהם התנאי מופיע פעמיים. זה אותו תנאי בדיוק. ההבדל היחיד הוא שפעם אחת שם העמודה הוא da.phone ובפעם השניה הוא da.Phone. בהנחה שאתה לא משתמש ב-Case Sensitive Collation, אין שום הבדל בין התנאים, ואפשר לאחד ביניהם.

    יש עוד דברים שאפשר לעשות כדי לפשט ולייעל את השאילתא. אני מניח שאחרי שתפשט אותה, היא תהיה מספיק פשוטה כדי שסדר הכתיבה לא ישפיע על בחירת ה-Execution Plan, מפני שה-Optimizer כבר יוכל להתמודד איתה בכבוד.

    בהצלחה!

    גיא גלנצר

    יועץ ומדריך SQL Server

    Madeira - SQL Server Services

    http://www.madeira.co.il/

    • הוצע כתשובה על-ידי Assaf_Shalem יום שני 09 אפריל 2012 10:37
    • סומן כתשובה על-ידי sharonof יום שני 16 אפריל 2012 07:16
    יום שני 09 אפריל 2012 09:30
    מנחה דיון