PDA

View Full Version : کدوم بهتره: تعداد جدول های بیشتر یا تعداد رکورد های بیشتر



محمد قانعی
یک شنبه 19 بهمن 1393, 23:01 عصر
با سلام.

من سه تا جدول دارم .(صندوق،اشخاص و بانک )که هر سه تا جدول همه فیلد هاشون یکی هستند.

حالا من میتونم با اضافه کردن یک فیلد برای نوع رکورد، رکورد های هر سه تا جدولم رو توی یکی از جدول ها ذخیره کنم.

این جوری جدول هام کمتر میشه ولی رکورد های اون جدول بیشتر میشه.

تعداد رکورد های اون جدول احتمالا به 1 میلیون نمیرسه.تعداد فیلدها هم 5 تاست.

خوب، برای سرعت بیشتر بیام سه تا جدول درست کنم یا برای بهینه کردن دیتابیس همه رکورد ها رو توی یک جدول ذخیره کنم؟

مهدی نان شکری
دوشنبه 20 بهمن 1393, 18:29 عصر
با سلام

این کار که به common lookup table معروف است معمولا اشتباه رایج طراحی دیتابیس می باشد که طرفداران زیادی هم دارد.
به چند دلیل این کار شما را دچار مشکل خواهد کرد:

1) با این کار معنای واقعی داده ها را از دست خواهید داد.
به عبارتی فرض کنید شما در جدول اصلی سیستم خود نیاز دارید یک کلید خارجی داشته باشید به اشخاص
اتفاقی که می افتد این است که شما یک کلید خارجی از جدول common lookup table (صندوق و اشخاص و بانک) به جدول اصلی خود ایجاد نمایید.
حال کاربر می تواند در مقدار این فیلد در جدول اصلی (که می بایست کد یک شخص وارد شود) کد صندوق رو وارد نماید در نتیجه domain integrity را نتوانستیم کنترل نماییم.

برای برطرف کردن این مشکل ممکن است فیلد CategoryTypeID را همراه فیلد ID جدول common lookup table کلید اصلی قرار دهید و در تمام کلید های خارجی از آنها استفاده کنید.
در این شرایط چند مشکل به وجود می آید که مهمترین آن نرمال نبودن جدول اصلی خواهد بود. (فرم نرمال 3 نخواهد بود زیرا فیلد CategoryTypeID به فیلد ID کلیدخارجی وابستگی تابعی دارد که خود جزو کلیدهای اصلی جدول اصلی نمی باشد)

2) نگهداری جدول مشترک مشکل خواهد بود. به عبارتی شما ناخواسته با چالش هایی روبرو خواهید شد.
مثلا ممکن است شما نیاز داشته باشید برای CategoryType های از جنس صندوق، نوع صندوق را هم نگهداری نمایید در نتیجه شما فیلدهایی خواهید داشت که برای بعضی از رکوردها بی معنی خواهند بود.

3)با این کار شما جدا سازی physical implementation از logical design را رعایت نکرده اید. و این دو به هم وابسته خواهند بود.

4) در سیستم های بزرگ ممکن است این جدول به چندین هزار سطر داده برسد که Lock و concurrency این جدول باید کنترل شود.

لذا توصیه عمومی بر این است که از common lookup table استفاده نشود و برای هر موجودیت جدول فیزیکی مجزایی طراحی شود.

با تشکر

محمد قانعی
دوشنبه 20 بهمن 1393, 19:22 عصر
ممنون.
من جدول هام همه فیلدهاش یکیه.
id=که کلید هست identity =yes
بعدش یه فیلد ایجاد میکنم برای این که بدونم رکوردم مربوط به کدوم جدوله.(مثلا مربوط به جدول صندوق)
بعدا که بخوام رکورد های جدول صندوقم رو نشون بدم با یک دستور select ساده می تونم این کار رو می کنم.(با where)
مفهوم کلید خارجی رو متوجه نمی شم.ولی من برای کلید جدولم از idاستفاده می کنم که از یک شروع میشه و یکی یکی بهش اضافه میشه.
باز هم عقیدتون به اینه که بهتره از 3 تا جدول استفاده کنم؟یا این که چون همه فیلد ها ی جدول هام یکی هستن و راحت میتونم رکورد هایی رو که میخوام select کنم بهتره از یک جدول استفاده کنم.
نظر تون رو بگین!ممنون.

مهدی نان شکری
دوشنبه 20 بهمن 1393, 23:37 عصر
من هم مورد شما رو دقیقا شرح دادم.

در صورت مسئله شما به جای اینکه چند جدول داشته باشید که همه آنها 2 فیلد که شامل ID و Title باشد 2 جدول که یکی از آنها شامل ID و Title و CategoryID خواهد بود و یکی دیگر نوع Category ها رو مسخص می کند.

در این شرایط مسائل بالا صادق است. اگر فرض کنید من بخواهم در جدولی که یکی از فیلد های آن شخص می باشد و از جدول بالا FK دارد کلیدی را ذخیره کنم کاربر اشتباها می تواند رکورد مربوط به صندوق را وارد نماید. در این شرایط دیتابیس شما با مشکل خواهد بود.

برای حل این مشکل می بایست شما ترکیب ID و CategoryID را یکجا کلید اصلی قرار دهید و در جدول مورد اشاره به صورت زیر استفاده کنید:


create Table User
(
ID int primary key,
PersonID int,
CategoryId int,
constraint ck check(CategoryId=2),
constraint fk foreign key(personid,categoryid) references basetbl(id,categoryid)

)


می بینید که با این شرایط می توان domain integrity جدول را حفظ کرد ولی جدول مورد اشاره نرمال سطح 3 نیست(همانطوری که در بالا شرح دادم).

از لحاظ Performance هم مشکلاتی خواهید داشت که در بالا به دو نمونه اشاره شد.

یکی از اشکالاتی که در نگهداری با آن برخورد خواهید کرد نیاز به ایجاد فیلد هایی برای مثلا فقط اشخاص باشد در این شرایط کلیه رکورد ها باید فیلدی را داشته باشند که ربطی به آنها ندارد.

محمد قانعی
سه شنبه 21 بهمن 1393, 08:45 صبح
با تشکر فراوان از nanshekari عزیز!:تشویق:
حالا یه سئوال دیگه که ربطی هم به این تایپیک نداره!
من میخوام بین دو تا از جدول هام ارتباط بر قرار کنم .
یه فیلد id دارم توی جدول اولم که یکی یکی بهش اضافه میشه(id=که کلید هست identity =yes)
حالا میخوام عدد id جدول اولم رو توی جدول دومم ذخیره کنم!برای این کار هم میام max id جدول اولم رو یکی بهش اضافه میکنم و توی جدول دوم ذخیره میکنم.
حالا سئوالم اینه که احتمال داره زمانی که به هر دلیلی کامپیوتر هنگ کنه یا سرعت بیاد پایین دو کاربر هم زمان این کار رو انجام بدن و عدد ذخیره شده در جدول دومم اشتباه بشه.
اگه راه های بهتری هم به نظرتون میرسه بگین ممنون از همهگی !:چشمک:

محمد قانعی
سه شنبه 28 بهمن 1393, 12:54 عصر
کسی نیست جواب سئوالم رو بدونه.

آخه اگه عدد ذخیره شده در جدول دوم همون عدد ذخیره شده جدول اولم نباشه به مشکل می خورم!خیلی مهمه که عدد رو اشتباه ذخیره نکنم.:افسرده:

مهدی نان شکری
سه شنبه 28 بهمن 1393, 15:51 عصر
با سلام
تابع SCOPE_IDENTITY() مقدار آخرین Identity اضافه شده در یک Scope را برای شما برمیگرداند. می توانید از این استفاده نمایید.
با تشکر