Archive for 2010/03

چند اشتباه در طراحی پایگاه داده

۱۳۸۸/۱۲/۲۹ ۲۱:۲۳ Salar Khalilzadeh https://plus.google.com/105397214522932500988 منتشر شده در تاریخ : ۱۳۸۸/۱۲/۲۹ دسته بندی : ، ، ، 5

Database - سال نو مبارک

چند ساعتی تا تحویل سال مونده، سال نو همه مبارک و امیدوارم که سال خوبی پیش رو داشته باشید.
سال گذشته که شخصا برام سال پر حادثه ای بود. اینطور که بوش میاد در سال جدید هم رویدادهای مختلف در انتظارم هستند، شاید وقت کمی برای نوشتن داشته باشم.

این مطلب رو هم مدتی قبل که یک پروژه نیمه کاره رو تحویل گرفتم تا کار کنم و از دست مشکلات پروژه ناراحت بودم نوشتم. پست با کمی ویرایش الان آماده شد!

سال نو همه مبارک و خوش و خرم باشید!

performance یا بازده، فاکتور خیلی مهمی در همه زمینه ها هست که معمولا توسط تازه کار ها و گاها توسط طراح دیتابیس فراموش میشود. معمولا در مرحله آموزش، بر روی کارهای کوچک و حجم کوچک اطلاعات مانور داده می شود. پروژه های آموزشی کوچک بوده و مثالها کاربردهای کوچک در مقابل داده های کم را در نظر می گیرند.

در دنیای واقعی وضعیت فرق میکنه. برنامه های نوشته شده باید برای مدت زمانی طولانی بدون مشکل پاسخ گو باشند. حجم داده های ورودی خیلی زیاد است. و در یک برنامه تجاری ممکنه این موارد برای چند صد تا چند صد هزار رکورد در روز هم برسد. در چنین شرایطی عدم رعایت چند نکته کوچک اما اساسی ممکن است مشکل ساز شود.

در ادامه می خواهم چند اشتباه در طراحی پایگاه داده رو مطرح کنم، به این امید که دیگر شاهد آنها نباشم. این موارد مطمئنن در طور دوره های آموزی به کرات مطرح می شود ولی شگفتا که هنوز هم عده ای این اشتباه ها را تکرار می کنند.

  • استفاده ازنوع داده های رشته ای به عنوان اندیس یا  کلید اصلی


نوع داده varchar و هر نوع داده کاراکتری یا رشته ای بدترین نوع انتخاب برای اندیس جدول است. این اشتباه زمانی بدتر خواهد شد که این فیلد به عنوان کلید اصلی نیز استفاده کنید؛ و سرانجام اشتباه با استفاده از این کلید به عنوان کلید خارجی تکمیل خواهد شد!

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

علت اشتباه بودن این انتخاب در ساخت جدول اندیس و تعداد مقایسه های انجام شده بر می گردد. به عنوان یک مثال ساده مقایسه ، دو نوع عددی می توانند به راحتی توسط دستور عمل های CPU با یکدیگر مقایسه شوند، در حالی که درنوع کارکتری باید تک تک کارکاتر ها با استفاده از شبیه سازی نرم افزاری مقایسه شوند. در رشته های یونیکد هم که حجم کاراکتر ها دو برابر می شوند.

راه حل: راه حل بسیار ساده استفاده از انواع داده عددی مانند int یا bigint است. در عین حال می توانید از سایر انواع ساده دیگر نیز استفاده کنید.

  • عدم استفاده از اندیس یا کلید اصلی


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

البته یک استثنا در این مورد هم وجود دارد. این مورد زمانی هست که انواع توصیفی را در جدولی جداگانه قرار می دهیم، که در این صورت چون داده های این جدول کم خواهد بود و حذف اضافه ای در کار نخواهد بود، می توان آن جدول را بدون اندیس یا کلید اصلی در نظر گرفت.

این نکته را هم در نظر داشته باشید که بدون کلید اصلی و یا یک کلید یکتا نمی توانید ارتباطی مابین جداول بر قرار کنید.

  • استفاده از فیلد های NULL بی مورد


همیشه در استفاده از فیلدهای NULL دقت کنید. سعی کنید که فیلدهای رشته ای را NULL قرار ندهید چونکه یک معنای زاید به آن فیلد داده اید، مگر اینکه واقعا به null نیاز داشته باشید. یک کاربرد مفید null بودن فیلد برای کلید های خارجی هست که نشان می دهد، هیچ ارتباطی در رکورد جاری تعریف نشده است. نمونه ای این کاربرد را در تصویر زیر مشاهده می کنید.
Database

در کنار استفاده از فیلدهای null می توانید از مقادیر پیش فرض هم استفاده کنید تا هیچ فیلدی ندانسته خالی رد نشود. این کار کدهای sql شما را هم کوتاه تر خواهد کرد.

در همین زمینه مطالعه کنید:

10 Common Design Mistakes

Ten Common Database Design Mistakes

Database Performance Philosophy

 

انتقال اطلاعات بین دو کلاس مختلف

۱۳۸۸/۱۲/۱۰ ۳:۰۳ Salar Khalilzadeh https://plus.google.com/105397214522932500988 منتشر شده در تاریخ : ۱۳۸۸/۱۲/۱۰ دسته بندی : ، ، ، 1

کد کوتاهی که در ادامه خواهید دید، یکی از کاربردهای ویژگی Reflection دات نت رو در برنامه نویسی روزمره نشون میده. کاربرد این کد بسیار ساده است در عین حال می تواند خیلی مفید هم باشد.  با یک مثال نشان خواهم که چقدر می تواند در برنامه نویسی به کمکتون بیاد.

کاری که این کد انجام میده، کپی کردن مقادیر ویژگی های عمومی (public property) هست. به عبارت دقیق تر مقادیر ویزگی های یک شیئ را به مقادیر ویژگهای همنام از شیئ دیگر کپی میکند.

این دو شیئ لازم نیست که هم نوع باشند. تنها شرط لازم داشتن ویژگیهای همنام هست. در صورتی که ویزگی ها نوع های متقاوتی داشته باشند، عمل کپی برای آن ویژگی انجام نخواهد شد.

مسلما می توانید این کد رو ویرایش کنید تا با نیاز های شما سازگاری بیشتری داشته باشد، اما قبل این کار باید کد را ببینید:
public static void CopyPropertiesValue(object sourceModel, object destModel)
{
Type sourceType = sourceModel.GetType();
Type destType = destModel.GetType();

foreach (PropertyInfo srcProp in sourceType.GetProperties())
{
PropertyInfo destProp = destType.GetProperty(srcProp.Name, BindingFlags.SetProperty | BindingFlags.Instance | BindingFlags.Public);
if (destProp!=null)
{
try
{
destProp.SetValue(destModel, srcProp.GetValue(sourceModel, null), null);
}
catch { }
}
}
}

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

  • مثالی از کاربرد


شاید با مثال بهتر بتوان به کاربر این تابع پی برد.

ابتدا تعاریف کلاسهای مورد استفاده:
class Person
{
public int PersonID { get; set; }
public string PersonName { get; set; }
public string PersonFamily { get; set; }
}
class Car
{
public int CarID { get; set; }
public int PersonID { get; set; }
public string CarModel { get; set; }
}

/// <summary>
/// کلاسی از ترکیب آن دو کلاس
/// </summary>
class Person_Car
{
public int CarID { get; set; }
public int PersonID { get; set; }
public string CarModel { get; set; }
public string PersonName { get; set; }
public string PersonFamily { get; set; }
}

در این نمونه کد مشاهده می کنید که مقادیر را می توانیم از کلاس Person_Car به دو کلاس بعدی انتقال دهیم:
public static void CopyModelTest()
{
Person person = new Person();
Car car = new Car();
Person_Car pCar = new Person_Car()
{
CarID = 10,
PersonID = 1,
CarModel = "ژیان :=)" ,
PersonFamily = "خلیل زاده",
PersonName = "سالار"
};

CopyPropertiesValue(pCar, car);

// کپی به کلاس Person
CopyPropertiesValue(pCar, person);
}

این تابع خیلی به من کمک کرده، امیدوارم که برای شما هم مفید باشه.