ייצוג מספר תעודת זהות בטבלה

jossefharush

New member
ייצוג מספר תעודת זהות בטבלה

שלום רב, אני מפתח מערכת שיש בה טבלת משתמשים ובה שדה מספר זהות כערך מספרי (bigint) שהוא גם Unique Constraint. באחד מהReviews שעשו לי, עלה מקרה קצה בו תעודת הזהות יכולה להתחיל עם הספרה 0, מה שעלול לגרום להתנגשויות בין 12345 לבין 012345 (שניהם יאוכסנו כ12345 מהסיבה שהשדה הוא מסוג מספר) הציעו לי לייצג את מספר תעודת הזהות כמחרוזת (varchar) האם מישהו נתקל בבעייה בעבר? אשמח לשמוע את דעתכם בנושא תודה, יוסף.
 

0 אור 0

New member
בדרך כלל מאכסנים תעודת זהות בשדה מחרוזת

בנוסף יש פונקציות (ברמת האפליקציה) שבודקות תקינות של המספר המוקש
 

jonjac

New member
מחרוזת!

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

sinaiy

New member
ספרת ביקורת.

ספרת ביקורת יוצרת אילוץ על המספרים כך שכנראה שלא ייתכן שגם 123 ו 0123 יהיו שניהם מספרי ת.ז שונים. (צריך לבדוק את אלגוריתים החישוב). אבל בדיוק מהסיבה הזאת הייצוג כ INT לא ייצג את מספר ה ת.ז האמיתי ו ייגרום בעיות בשימוש בערך ככל דבר מאשר כ UNIQUE USER ID פנימי
 

גרי רשף

New member
מחרוזת (תירוץ נוסף)

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

כלליים

New member
מספר זהות

הוא לעולם בן 9 ספרות. ולכן, המספר 12345 הוא 000012345. אם תבחר להשתמש בשדה מספרי ולא במחרוזת, פשוט עצב את השדה בפורמט "000000000" או "000-000-000".
 

sirpad

New member
אם אתה מתעקש על מספר תשתמש בint

שכן מספר זהות בן 9 ספרות נכנס בתוך int בלי בעיה. מה שכן עדיף לך לעבוד עם מחרוזת, בגלל שת"ז היא לא מספר אמיתי. אם אתה הולך על המחרוזת, אז אין טעם לעשות varchar, כשאתה יודע מראש שמדובר במחרוזת בעלת אורך קבוע של 9 תוים. זה הרבה יותר חסכוני, וייתן לך ביצועים יותר טובים להשתמש ב
char(9)​
במקרים בהם גודל המחרוזת הוא קבוע.
 

jonjac

New member
ביצועים

אתה מצליח לראות הבדל בביצועים בין CHAR לבין VARCHAR?
 

sirpad

New member
תגדיר ביצועים?

המחיר בין char וvarchar הוא תוספת של 2 בייט, במחרוזת של 9 תווים ההבדל הוא אם כן בין 9 ל11 בייט, גידול של 22%! עכשיו זה לא מה שיהרוג את השאילתות ה2 הללו, נכון, אבל זה בזבוז כשאתה יודע מראש שאתה תמיד תשתמש במחרוזת בגודל קבוע של 9. אז לא בגלל שvarchar יפיל את המערכת, אבל השימוש בו יבלבל ולא יסביר בצורה ברורה שהמחרוזת חייבת להיות בת 9 תווים. בעיה אחרת שצריך לחשוב עליה כשמשתמשים בvarchar היא שאם לא ממלאים את כל המקום שניתן בהגדרה של העמודה, אז כשמעדכנים את העמודה, ואין מקום בדף, נוצר פייג' ספליט! ולכן שימוש בvarchar שלא לצורך יכול לגרום לבעיות אחרות, שאחרי כמה חודשים או שנים של עבודה פתאום יתנו בעיות בביצועים. הסיבה הכי חשובה לדעתי במקרה זה היא ששימוש בchar הוא הזול ביותר, ולא מגביל את המערכת בשום דבר! מה שאין בו טעם לא עושים, נקודה.
 

jonjac

New member
זה אתה שהשתמש במילה ביצועים

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

sirpad

New member
אם המחרוזת היא תמיד באורך קבוע

אז זה בזבוז להחזיק 2 בייט כדי לדעת מהו האורך של המחרוזת. אני לא יודע איך אורקל מיישמים את זה, אבל ה2 בייט משומשים למידע על אורך המחרוזת. אם הוא תמיד תשע, אז אין טעם לעשות מחרוזת עם אורך משתנה שלעולם לא תשתנה. אם אורך המחרוזת משתנה, ביותר מ2 תווים, אז זה משתלם לשלם 2 בייט. כאתה סובל מפייג' ספליט, זה משפיע על הביצועים של השאליתה. גם על השאליתה שכותבת וגורמת לפייג' ספליט, וגם יש לך פתאום 2 דפים כמעט חצי ריקים כדי להכיל את מה שקודם היה ניתן להכיל בדף אחד, ואם יש לך הרבה כאלה אז יש לך המון מקום שמבוזבז על כלום. ואם אתה צריך לקרוא 1000 דפים מהדיסק במקום 550, למשל, אז גם זה משפיע על הביצועים. תעודת זהות זה לא סתם עמודה בטבלה, סביר מאוד להניח שיכתבו כמה וכמה אינדקסים כדי לכסות דרישות של שאילות שמחפשות ו/או מציגות את המידע הזה, כך שהמקום שזה תופס הוא אולי בחזקת מספר האינדקסים, שלוש אולי ארבע אינדקסים. גם אם הכל זה פינטס לעומת המסד נתונים שהוא בונה, היינו שלא מדובר ברשומות של מיליון אזרחים ויותר, עדיין אין סיבה להשתמש בvarchar, אם זה אף פעם, לעולם לעולם לעולם, לא יהיה פחות מ9 תווים במחרוזת.
 

jonjac

New member
באורקל

באורקל הוא שומר בבלוק לכל שדה, לא חשוב מאיזו עדה, את אורך השדה. האמת היא שאני אתפלא אם זה לא מה שקורה גם בMSSQL מאחורי הקלעים.
 

sirpad

New member
אבל אם האורך הוא שונה

כלומר איפה נשמר הערך של האורך פר שורה? לדוגמא, שדה של שם פרטי מסוג varchar2 באורך 20: מנחם זרובבל אלכסנדר אבן-יהושוע קונסטנטינוס שי רותם מיכל אוחזת ענף עץ השקד איפה נשמר הערך של אורך המחרוזת בשורה של קונסטנטינוס? שי? מיכל? לגבי SQL SERVER בוודאות, אלא אם MS משקרים בתיעוד שלהם, הגודל של varchar שווה ל2 בייט פלוס האורך של המחרוזת.
 

sirpad

New member
ולא שזה אומר משהו רע על אורקל

אבל מסתבר שבאורקל גם char מבזבז 2 בייט על אורך המחרוזת...
A varchar2 datatype, when stored in a database table, uses only the space allocated to it. If you have a varchar2(1999) and put 50 bytes in the table, we will use 52 bytes (leading length byte). A char datatype, when stored in a database table, always uses the maximum length and is blank padded. If you have char(1999) and put 50 bytes into it, it will consume 2001 bytes (leading length field is present on char's as well). In the database -- a CHAR is a VARCHAR that is blank padded to its maximum length.​
בעוד שSQL SERVER
char and varchar (Transact-SQL) SQL Server 2008 R2 Other Versions Are character data types of either fixed length or variable length. char [ ( n ) ] Fixed-length, non-Unicode character data with a length of n bytes. n must be a value from 1 through 8,000. The storage size is n bytes. The ISO synonym for char is character. varchar [ ( n | max ) ] Variable-length, non-Unicode character data. n can be a value from 1 through 8,000. max indicates that the maximum storage size is 2^31-1 bytes. The storage size is the actual length of data entered + 2 bytes. The data entered can be 0 characters in length. The ISO synonyms for varchar are char varying or character varying.​
 

jonjac

New member
לגבי אורקל

זה מה שאמרתי - שהוא שומר לכל שדה, לא חשוב מאיזו עדה, את אורכו. לגבי CHAR של MS-SQL תודה על ההבהרה. מסתבר שמבחינת נפח נתונים זה אכן DATATYPE יעיל יותר.
 

jonjac

New member
ייצוג פנימי

אני לא מבין איפה בדיוק הבעיה. לפני כל ערך ברשומה אורקל מוסיף בייצוג הפנימי שני בתים שמייצגים את אורך השדה. אין למשתמש גישה לשנות את שני הבתים שמייצגים אורך שדה. (אבל אפשר לשלוף אותם). לגבי MS-SQL, אתה מתאר את דרך שמירת VARCHAR אבל מה עם דרך שמירת CHAR? אולי גם שם הוא שומר 2 בתים?
 
למעלה