ארכיון

Archive for the ‘פיתוח’ Category

ההרצאה שלי "Introduction to Big Data and NoSQL solutions" זמינה ב-YouTube

http://www.youtube.com/watch?v=4dGzaOJRVag

 

ההרצאה ניתנה בפורום ISUG (ארגון משתמשי SQL Server בישראל) במיקרוסופט רעננה ב-9 באפריל 2013.

תגובות והערות יתקבלו בברכה.

מודעות פרסומת

איך לדפדף עם SQL Server 2011

ב- SQL Server 2011 ישנה אופציה חביבה המפשטת מאד את פעולת ההבאה של קבוצת נתונים (או דף) מתוך כלל תוצאותיה של שאילתא. מדובר בביטוי חדש בשם OFFSET הבא כתוספת לאחר ביטוי Order by והמבנה שלו הוא זה:

 

<offset_fetch> ::=

{

OFFSET { integer_constant | offset_row_count_expression } { ROW | ROWS }

[

FETCH { FIRST | NEXT } {integer_constant | fetch_row_count_expression }

{ ROW | ROWS } ONLY

]

}

לדוגמה: נניח שאנו מחלקים את תוצאות השאילתה לדפים בגודל 10 שורות כ"א. אם נרצה לשלוף את הדף השני נבצע משהו כזה:

select *

from Production.Product

order by name asc

offset 10 rows

fetch first 10 rows only

 בדוגמה שלפנו מטבלת המוצרים את 10 המוצרים שבדף השני (מיון לפי שם המוצר), כלומר המוצרים במיקום 11 עד 20 ע"פ המיון שנבחר.

אין ספק שזה נוח להפליא. השאלה היא: האם SQL Server חכם מספיק כדי לשלוף את הדף הרצוי בצורה המהירה ביותר?

התשובה: שיחקתי עם זה קצת ובחנתי את ה-execution plans, ואכן ה-SQL Server יודע לשנות את ה-plan לפי ה-offset ולפי כמות הנתונים המבוקשת:

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

 

הפיצ'ר הזה לדעתי הוא פיצ'ר שישפר את הביצועים באופן אמיתי כשמדובר בשליפת "דפים" כשמשווים אותו לכל צורת דפדוף אחרת (לרוב בשימוש עם row_number() ועם שאילתא בתוך שאילתא).

אין ספק שזו תוספת נחמדה ומקורית (אני לא מכיר כזה פיצ'ר באורקל).



לפתוח דף חדש

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

יש למעשה שתי שיטות דפדוף עיקריות (ועוד אחת בהמשך):

  1. שרת האפליקציה קורא את כל הרשימה מה-DB אל מבנה בזיכרון (כמו DataSet בדוט נט) ומשם הוא מבצע rendering ל-HTML רק את המידע שיש להציג בדף.
  2. שרת האפליקציה מפעיל SQL על כל פעולת דפדוף ומביא מה-DB רק את המידע הרלוונטי שיש להציג בדף הנוכחי.

יתרונות וחסרונות

שיטה

יתרונות

חסרונות

1

מתבצעת קריאה בודדת לשרת ה-DB

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

2

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

כל פעולת דפדוף יוצרת ביצוע שאילתא ב-DB

 

מדוע השיטה השניה עדיפה? בגלל הפסיכולוגיה של משתמשים באינטרנט. משתמשים לא אוהבים לדפדף יותר מדי. אם, למשל, נשלפו 10000 פרטים ומוצגים 20 פריטים בדף (כלומר נוצרים 500 דפים), אזי המשתמשים לרוב יסתכלו בדף הראשון והשני. הסיכוי שיבחרו להסתכל בדף מס' 392 הוא לרוב קלוש מאד. בגוגל יודעים זאת היטב ומנגנון שליפת תוצאות החיפוש בנוי כך שנקבל מהר את תוצאות החיפוש של הדפים הראשונים.

ישנה גם שיטה מס' 3 שהיא שילוב של שיטה 1 ו-2. בשיטה זו יוצרים "מגה דף" בזכרון, כלומר, מעלים ל-DataSet כמה דפים (כלומר סוג של cache). אם נשתמש בדוגמה שלעיל, נבנה "מגה דף" של 100 פריטים ("מגה דף" = 5 דפים). כשהמשתמש יבקש לראות את דף 2 (פריטים 21 עד 40) אז נציג את הפריטים מה-DataSet ולא נבצע קריאה נוספת ל-DB.

שיטה 3 – יתרונות וחסרונות

שיטה

יתרונות

חסרונות

3

הרבה פחות קריאות ל-DB מאשר בשיטה השניה וצריכת הזכרון בשרת האפליקציה קטנה בהרבה מבשיטה הראשונה.

מנגנון ה-Caching הזה (בדוגמה, 5 דפים), קצת יותר מורכב לפיתוח. צריך לדעת מתי לקרוא מה-DB ומתי לקרוא מה-cache.

 

איך לבנות Data Access Layer כמו שצריך

אני מייעץ לכל מיני חברות: גדולות, בינוניות וגם קטנות. מטבע הדברים, בחברות הקטנות ישנה גמישות רבה יותר לרעיונות חדשים ונכונות לשנות ולתקן טעויות הסטוריות.

בחברה אחת שכזו נעשית חשיבה כיצד נכון בשבילם לכתוב את ה-DAL.

האפשרויות הן:

  1. כתיבת משפטי SQL בתוך הקוד. לרוב נבנה הטקסט של המשפט והוא נשלח לביצוע ל-DB.
  2. קריאה ל- Stored Procedures מתוך הקוד והעברת פרמטרים אליהם ומהם.
  3. שימוש ב-ORM או Object Relational Mapping כמו Hibernate או Entity Framework.

אופציה מספר 1 (SQL בתוך הקוד) היא הגרועה שבהם וזאת מכמה סיבות ואלו העיקריות שבהן:

  1. משפטי ה-SQL שבקוד אינם נבדקים בזמן קומפילציה ועלולים "להתעופף" בזמן ריצה אם התחביר שגוי.
  2. שינויים בסכימה (הוספת/ביטול עמודות, שינוי טיפוס נתונים, שינוי בשמות טבלאות וכו') גוררים שינויים בקוד. קשה למצוא את כל המקומות שיש לשנותם. ה-deploy בסביבת היצור חייב יהיה לשנות את הקוד שמעל ה-DB.
  3. השאילתות שנוצרות בקוד הן לרוב – שאילתות דינאמיות עם כל המשמעויות המתבקשות של בעיות ביצועים.

לאופציה מספר 2 (Stored procedures)  יש גם כן מגרעות (אבל פחות מאשר לאופציה מס' 1):

  1. קריאה לפרוצדורות היא סוג של יציאה מעולם האובייקטים לעולם רלציוני – מה ששובר את עקרונות עיצוב מונחה עצמים.
  2. במערכת בינונית ומעלה אפשר למצוא מאות ואפילו אלפי פרוצדורות. אי אפשר למצוא את הידיים ואת הרגליים בהם והרבה פעמים קורה שמפתח כתב stored procedure ולא ידע שמישהו אחר כתב את אותה פרוצדורה לפניו – רק עם שם אחר.
  3. הרבה פעמים הלוגיקה העסקית "מתפזרת" לתוך פרוצדורה ואז היא מצוייה גם בשכבת BLL וגם בשכבת ה-DAL.
  4. לא כל כך נוח לתכנת כל פעולת SQL בשני שלבים – פיתוח קריאה לפרוצדורה בשפה עילית ופיתוח הפרוצדורה בשפת ה-DB (כמו PL/SQL או T-SQL).

לאופציה מספר 3 (ORM) יש גם מגרעות:

  1. קוד ה-SQL שמחולל ע"י ORM עלול להיות לא יעיל בעליל. ככל שרמה הסיבוכיות עולה – הסיכוי שה-SQL שנוצר יהיה איטי גובר.
  2. עבודה עם ORM דורשת לימוד מעמיק של היכולות והמגבלות.
  3. קשה לנסח שאילתות מורכבות בממשק כמו LINQ או HQL. מה שהולך בקלות ב-SQL, הולך קשה ב-LINQ.

מה עושים?

לדעתי – יש לנסות לקחת את הטוב משתי האופציות 2 ו-3. כלומר – כן ליישם ORM – אבל לשלב אותו עם Stored procedure אותם יש לכתוב בשביל משימות שה-ORM מתקשה ליישם בצורה אופטימלית.

עיבוד טרנזקציות? נוח מאד ב-ORM. שאילתות מורכבות? לך על Stored Procedures וחבר אותם ל-ORM.

אשמח לשמוע על רעיונות נוספים.

איך הגעתי בכלל לבסיסי נתונים

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

זה התחיל בשנת 1988 כשהתגייסתי לצה"ל ועשיתי קורס תכנות בממר"ם. באותם הימים שפות הפיתוח הפופולאריות היו C, פסקל  ו-Ada על מערכות VAX/VMS ו- PL/1 וקובול על מיינפריים של IBM. בתום הקורס ביקשתי הצבה בחיל מודיעין ואכן הוצבתי ביח' המחשבים של חמ"ן. מייד לאחר שהגעתי ליחידה, נשלחתי לקורס פיתוח מתקדם ב- VAX/VMS  ולאחריו המערכת הראשונה שבה פיתחתי הייתה מערכת העובדת על אורקל גרסה 6 שרץ על VAX/VMS . זו הייתה הפעם הראשונה שראיתי בסיס נתונים רלציוני ופעם ראשונה שנתקלתי בשפת SQL.

באותה תקופה לא היה תפקיד כזה שהיום נקרא DBA. היה זה פשוט עוד "כובע" שאחד המפתחים היה חובש בנוסף לשאר המטלות שעליו לבצע. רק כמה שנים טובות אחר כך, זה הפך למקצוע של ממש. כך השתמשתי באורקל בפרויקטים שונים והיו גם פרויקטים שלא השתמשתי בבסיס נתונים רלציוני בכלל אלא במערכות מפתוח נתונים שאינן סטנדרטיות. היום קשה לראות מערכת IT שאינה מורכבת על DB מסחרי – אבל לפני 18 שנה זה היה מקובל.

בשנת 1997 פגשתי את זיו מנדל, מנכ"ל ג'ון ברייס הדרכה. זיו היה מפקד קורס שלב 9 (או שלב 11, אני כבר לא זוכר) כשהייתי בצבא והוא זכר אותי. זיו הציע לי ל"התגייס" לקבוצת ג'ון ברייס (שאינה קיימת היום) גם כמנהל תחום הדרכת DBA וגם כיועץ אורקל וכך עשיתי. ג'ון ברייס היה בי"ס מעולה בשבילי ולמדתי שם כל מה שאפשר על אורקל וגם על טכנולוגיות אחרות (כמו FW, ג'אווה, שרתי אפליקציות ועוד) בנוסף הסתובבתי בין לקוחות שחיפשו עזרה בעבודה עם אורקל. הימים הם ימי הבועה. קורסי ה-DBA שהייתי מרצה בהם (DBA 1,2,3) היו מפוצצים עד אפס מקום, במיוחד כשיצאה באותם הימים גרסה 8 ואחריה 8i. אורקל הייתה מלכת ה-DB ולמעשה נתנה פתרון בכמה רמות מעל המתחרים (שהיו Informix, DB2, Sybase). היה אז גם מוצר קטן ושולי בשם SQL Server 7 של מיקרוסופט אבל הוא התאים רק למערכות קטנות עם משתמשים מועטים ולא היווה אז גורם משמעותי בתחרות מול אורקל.

במאי 1999 פנו אליי מחברת הסטארט אפ ImageID שגייסה סכומי עתק והציעו לי להצטרף כ-DBA ואיש פיתוח Web. לא היה אז איש תוכנה אחד בישראל שלא חלם על אופציות דשנות ועל המיליונים שהוא עתיד לעשות איתם. כל חודש היה אקזיט של חברה אחרת עם סיפורים על אנשים שסגרו משכנתאות ואפילו פנסיות בזכות האופציות שהיו ברשותם. על הנייר – הייתי יכול לקנות דירה נאה מאופציות שלי. על הנייר… כמובן שבהמשך יכולתי לעשות מהאופציות אוריגמי של בית מנייר….

ב-ImageID לימדתי את כולם לעבוד עם אורקל. אני בעצמי הייתי חצי מהזמן DBA וחצי מהזמן איש פיתוח (בעיקר ב-ASP, VB ו-C++).  בשנת 2003 החלטנו בחברה להיכנס לעולם הדוט נט. אני למעשה הראשון בחברה שלמד דוט נט ו-ASP.NET וכך הפכתי לר"צ WEB בחברה. במקביל המשכתי להיות איש האורקל של החברה. בשנת 2004 בחנתי את SQL Server 2000 ואת MSDE כבסיס נתונים עבור פרוייקט לחברה גרמנית עם סניפים רבים. חיפשנו DB זול יחסית שיעבוד בסניפים ויעביר נתונים ל-DB מרכזי שמריץ אורקל ב- XML באמצעות web services. זו הייתה הפעם הראשונה שנתקלתי ב-SQL Server. האמת – לא ממש התלהבתי ממנו. כאיש אורקל היו חסרים לי המון פיצ'רים במערכת הזו. במיוחד לא אהבתי שלא היה שם row versioning (מה שנקרא snapshot isolation). בשנת 2005 יצאה מיקרוסופט עם SQL Server 2005 וסופסוף היה כאן מוצר שיכול להוות אלטרנטיבה לאורקל. אני התחלתי לעבוד איתו באינטנסיביות כשעזבתי את ImageID והצטרפתי לחברת סטארט אפ אחרת בשם MutualArt ולאחר מכן גם באמדוקס וכיום ב-SRL.

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