many to many without junction table

flenger

New member
many to many without junction table

שלום לכולם
אני הייתי רוצה לדעתכם מבחינת ביצועים על המצב הבא
נניח ויש 2 טבלאות A ו B אשר יש בינהם יחס של MANY TO MANY
יש 2 אפשרויות "לפתור" את הבעיה
1. ליצור JUNCTION TABLE - שזה הפיתרון ה"קלסאי"
2. שבאחת הטבלאות נאמר B יהיה 2 שדות של FromID ו ToID מטבלא A

השאלה מה יותר טוב מבחינת ביצועים
תודה מראש לעוזרים
 

גרי רשף

New member
למה הכוונה באפשרות 2?

בדרך כלל Pitoach הוא זה שמבקש DDL, אלא שהפעם אקח על עצמי את התפקיד:
מה יש בכל אחת משתי הטבלאות?
מההצעה שלך עולה שכל שורה מטבלה B מקושרת לשתי שורות לכל היותר בטבלה A. האמנם?
 

flenger

New member
התשובה טיפה מורכבת ולכן אהיה ספציפי יותר

יש 2 טבלאות INSPECTION ו INDICATION
בכל INSPECTION יש הרבה INDICATIONS אך INDICATION יכול להיות קיים לאורך זמן לכן קיימת הטבלת הMANY TO MANY
נאמר INDICATION מסויים והוא קורא לאורך 5 INSPECTIONS בטבלת הMANY TO MANY יהיו 5 רשומות
אם הINDICATION משתנה למשהו אחר הוא יקבל ID חדש ובהתאם גם INSPECTION חדש
אבל .. אם מתקבל שוב אותו INDICATION שהיה בעבר הוא שוב יקבל ID חדש
מה שאומר שכל INDICATION יש רצף של INSPECTIONS ולא יכול להיות מצב ש INDICATION מקושר עם ID 1 2 3 4 6 7

לכן חחשבתי שממבחינת ביצועים וחחסכון בטבלה נוספת יהיה "נכון" יותר להוסיף לטבלת INDICATION שתי שדות נוספים FromInspectionID ו ToInspectionID
צריך לקחת בחשבון שאותו INDICATION יכול להתקבל במשך חודשים על גבי חודשים זאת אומרת שטבלת הMANY TO MANY סתם מתנפחת בלי שום תועלת
וסתם פועל בביצועים של שאילתות כי הטבלה המקשרת מגיעה לגדלים עצומים

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

גרי רשף

New member
אם אני מבין נכון- זה אחת לרבים (1:N)

לכל Inspection יש כמה indications ברצף,
ואז יש שתי אפשרויות:
1. הדרך המקובלת לציין בכל Indication מה ה-Inspection שלו (Foreign Key).
2. לציין בכל Inspection מה ה-Indication הראשון ומה האחרון.
הבנתי נכון (לפני שאני מעלה השערות מה יותר יעיל)?
 

flenger

New member
קודם כל תודה על התשובות

היחס הוא אינו יחיד לרבים
מצד אחד בכל INSPECTION יכולים להתקבל הרבה INDICATIONS שונים
ומצד שני INDICATION ספציפי יכול להתקבל לאורך הרבה INSPECTIONS
אז נראה שהפתרון הנכון הוא ליצור טבלה מקשרת

אבל כמו שציינתי אם יש INDICATION נקרא לו A שמתקבל לאורך תקופה מסויימת נניח 5 INSPECTIONS לכן אמרתי מקודם שיש להוסיף 2 שדות המציינים תקופה של מ - עד
ואז מתקבל INDICATION חדש נקרא לו B
ואז שוב מתקבל אותו INDICATION A יווצר לו ID חדש ולא אותו ID ישן למרות שמדובר באותו INDICATION

שוב תודה לעוזרים

** סיבה הבעיה היא טכנולוגית מיכוון שאנחנו משתמשים ב EF בכל פעם שאנחנו מנסים לבצע עדכון לINDICATION / INSPECTION נעשת שליפה דרך הטבלה המקשרת
שכמו שאמרתי היא מאוד גדולה
גם בדרכים שבה מעדכנים את אותה טבלה מקשרת בלבד ... עדיין יש בעיית ביצועים .
 

pitoach

New member
אם אתה מדבר באמת על מסד נתונים גדול אז אתה

עושה כניראה טעות גדולה מאוד באפיון שלך

EF לא נועד למערכות כבדות אלא לנוחות של מפתחים שמחפשים מהירות פיתוח ולא מיטוב של התוצאה!
* זה דבר נכון לכל ORM בעיקרון

אני מאוד מציע לך לבדוק את השאילתות שמגיעות מה EF אל השרת SQL בעזרת הפרופיילר של ה SQL ולגלות שיכולת לכתוב לבד שאילתות יותר מיטביות

* כלי נוסף שהייתי ממליץ לך זה להתקין באפליקציה את הספרייה של MVC MiniProfiler דרך ה nuget
זה יעזור לך להבין מה קורה אצלך בפועל מאחורי הקלעים וזה כלי מאוד מומלץ אם כי הוא עדיין בשלבי פיתוח.
 

גרי רשף

New member
תוכל לתת דוגמה?

למשל- יכול להיות דבר כזה?

Idic. Inspec.
1 1
1 2
2 2

כלומר- Indication=2 שייך גם ל-Inspection=1 וגם ל-Inspection=2,
ו- Inspection=1 שייך גם ל-Indication=1 וגם ל-Indication=2.
אם לא- תוכל לתת דוגמה לנתונים שמקיימים אצלך יחס של רבים לרבים?
לא את כל הטבלה אלא רק השורות המהותיות.
 

flenger

New member
כמובן

קודם אני רוצה לציין שאני ממש לא בעד כלי ORM אבל זאת החלטה שנלקחה והיא מעבר יכולות שלי
אני מכיר את הפרופיילר והצלחתי להביא את ה EF לייצר שאילתות בצורה הקרובה ביותר למה שאני רוצה אך עדיין זה לא מספיק
לגבי הדוגמה שלך היא אכן טובה
אך ניתן אחת נוספת

InspID IndID
1 1
2 1
3 1
1 2
2 2
1 3
* כפי שניתן לראות INSPECTION הראשון יש 3 INDICATIONS
בשני התקבלו 2 שחוזרים על עצמם מהפעם הקודם 1 ו 2
ובשלישי רק הראשון חוזר
מה שלא יכול להיות הוא
2 4
1 5
 

pitoach

New member
לאיזה מצב אתה קורא חזרה? האם לנתונים של

1-2
2-1
מבינתך זה חזרה וצריך למנוע את זה?
אם כן זו פעולה פשוטה של הוספת תנאי לטבלה. אפשר פשוט להוסיף תנאי של CHECK Constraint פשוט.
* עדיין זו דוגמה פשוטה של יחס רבים לרבים שמבוצע באמצעות טבלה מקשרת. ואת התנאי שמים על הטבלה המקשרת למשל.
** העובדה שאתה עובד ב EF רק מחזקת שזה הכיוון המתאים מפני שכל הקשר רבים לרבים כפי שאתה יודע וכתבת, מנוהל בעזרת טבלת מקשרת באופן ברירת המחדל
*** EF לא תומך לידיעתי בתנאים שמוסיפים ידנית ועלייך לכסות באפליקציה לכן את המצב של שגיאה בגלל אי-עמידה בתנאי במסד הנתונים (אפילו הכנסה לבלוק TRY יכולה להספיק).

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

flenger

New member
לא צריך למנוע את החזרה

היא פשוט לא קיימת
הכוונה שלי שבמקום שיהיה לך נאמר 5 רשומות המייצגות טווח שבוא INDICATION התקבל בINSPECTION שונים בזמניםם שונים
נראה לי יותר נכון מבחינת נרמול של נתונים להוסיף 2 שדות המייצגים את אותו טווח
ואז בשליפה
במקום לעשות ככה

SELECT *
FROM INDICATION IND
JOIN IndINS ON IND.ID = IndIns.IndID
JOIN INSPECTION INS ON INS.ID = IndIns.InsID

נעשה ככה
SELECT *
FROM
INDICATION IND
JOIN INSPECTION INS ON IDS.FromIns >= INS.ID AND IND.ToIns <= INS.ID
 

גרי רשף

New member
סופסוף הבנתי..

גם השתכנעתי שמדובר ברבים לרבים,
וגם הבנתי את ההצעה שלך- בהנחה שה-IndID רציפים לכל InspID.

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

בכל מקרה- רעיון יפה, ואולי אבדוק אותו בעצמי..
 

pitoach

New member
אני מניח שכן יהיה עדיפות לשיטה זו אם מדובר

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

* האפיון של "נתונים רציפים" הוא נתון מאוד מהותי כאן שמהווה תוספת חשובה לאפיון (לפחות כמו גרי גם אני לא עליתי על כך למרות שכן נכתב על הרציפות קודם
ורק עתה הבנתי מה הכוונה)
לכן תמיד חשוב לצרף DDL+DML כשאפשר.

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

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

zalomon

New member
מציע להשאר עם טבלה מקשרת

ראשית משהו לא מובן לי. יש MANY TO MANY, אבל לכל INDICATION יש רצף של INSPECTIONS -- רציפים.
האם לכל INSPECTION יכול להיות יותר מ- INDICATION יחיד? נשמע מודל מוזר. ואז איך הרציפות עובדת?

אבל נניח וזה כך והכל בסדר. לכאורה ה- "מ-" ו-"עד" קומפקטיים יותר, אבל תגלה ש:
- שאילתות יהיו סבוכות יותר (איך מגלים מהו ה-INSPECTION של INDICATION מספר 2987892?) האינדקסים על INDICATION אינם טריוויאלים
- בכיוון השני ה- JOIN יהיה על טווח במקום על שוויון. תגלה שכלים שונים (ORM-ים למשל) לא אוהבים כזה JOIN ותצטרך לקודד יותר בעצמך או לעקוף מגבלות.
- נשמע כאילו טבלת ה- MANY TO MANY היא גדולה? סבה"כ יש שם שני מספרים. אני מנחש שביחס לשתי הטבלאות המקוריות היא לא תהיה גדולה כל כך.

במקרה הזה, ודווקא לאור המוזרות של המודל, הייתי נשאר עם נורמליזציה, כלומר עם טבלה מקשרת
 

flenger

New member
אני לא יודע עד כמה אתה צודק

נכון שלפי איך שזה נראה , הדבר הנכון ביותר הוא להשתמש בטבלה מקשרת
אבל אם אני אגיד לך שבכל INSPECTION יחיד יכול להתקבל לך 100 אלף ואפילו יותר INDICATIONS
ונניח שאתה מבצע את אותו INSPECTION פעם ביום אתה מאוד מהר מגיע לטבלה של כמה מליוני רשומות

לכן היה נראה לי שדווקא הפתרון של להוסיף 2 שדות נראה טוב יותר
ממה שבדקתי נראה שזה לוקח פחות זמן
 

pitoach

New member
אני רק מנחש שלא בדקת מספיק לעומק עדיין

או אולי הסתמכת על כלים מוכנים כמו ORM שיבצעו עבורך את העבודה.

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

לשם בדיקות עלייך לבדוק שנפרד את השאילתות מול מסד הנתונים בלי קשר לאפליקציה ורק בסיום לבדוק את הקשר לאפליקציה. אם אתה מסתמך על EF שיכתוב לך שאילתות אז גם כתבתי לך למעלה כיצד לאתר אותן ב 2 דרכים (הדרך של ה DBA היא פרופיילר של ה SQL והדרך של המפתח היא פרופיילר של EF מוכן או שכותבים לבד)

אני מקווה שזה עוזר מעט
 

flenger

New member
אני חושב שמגיע לי קצת יותר קרטיד :)

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

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

flenger

New member
אני חייב לציין דבר נוסף

אני מאוד התנגדתי לשימוש בEF
אך מיכוון שלוקחי ההחלטות אצלנו בחברה סוגדי MICROSOFT היה קשה לשכנע אותם אחרת

אני אישית אמרתי שבכל מקום שיש DB הולכים על הדבר הבסיסי ביותר
ואפילו אמרתי שעדיף לעבוד מול DATASET ליייצר את השאילתות בצורה היעילה ביותר בDATABASE
ובכך להביא לביצועים הטובים ביותר

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

pitoach

New member
כולנו "קורבנות" של הלקוחות/בוסים/נסיבות


אבל העבודה עם EF היא לא גמישה יותר בשום אופן אלא הפוך
. EF מייצר הרי שאילתות עבורך כך שכל מה ש ORM עושה לך אפשר בלי ORM אבל הפוך לא

ז"א ORM תמיד פחות גמיש

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

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