سلام.
برای داشتن یک برنامه بهینه شما نیاز به کدهای بهینه و الگوریتم های بهینه خواهید داشت.
فرض کنید که میخوایم مجموعه ای از رکوردها رو بصورت همزمان درج کنیم. شاید برای این کار دو قطعه کد زیر متصور باشه :
con = new SqlConnection("Data source =(local);initial catalog = testgrid;integrated security = true");
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
SqlCommand cmd = new SqlCommand("insert into student2 values(" + dataGridView1.Rows[i].Cells[0].Value + ",'" + dataGridView1.Rows[i].Cells[1].Value + "',N'" + dataGridView1.Rows[i].Cells[2].Value + "',N'" + dataGridView1.Rows[i].Cells[3].Value + "'", con);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
قطعه کد دوم :
for (int i = 0; i <= t - 1; i++)
{
if(Convert.ToBoolean(dataGridView1.Rows[i].Cells[4].Value) == true)
{
s = s + "insert into student2 values(" + dataGridView1.Rows[i].Cells[0].Value + ",'" + dataGridView1.Rows[i].Cells[1].Value + "',N'" + dataGridView1.Rows[i].Cells[2].Value + "',N'" + dataGridView1.Rows[i].Cells[3].Value + "')" + ";";
}
}
s = s.Remove(s.Length - 1, 1);
con = new SqlConnection("Data source =(local);initial catalog = testgrid;integrated security = true");
con.Open();
SqlCommand cmd = new SqlCommand(s, con);
cmd.ExecuteNonQuery();
con.Close();
هر دوی این دستورات یک کار مشترک رو انجام میدن اما به دو روش متفاوت. اولی به تعداد رکوردهای موجود در گرید عمل اتصال به دیتابیس رو انجام میده و هر بار یک رکورد رو درج میکنه و دوباره ارتباط رو قطع میکنه. ولی دستور دوم درون حلقه همه رکوردها رو جمع میزنه و در خارج از حلقه با یکبار وصل شدن به دیتابیس عمل درج چندین رکورد رو انجام میده. کدامیک از این روش ها سریعتره؟
گول تعداد خط کد کمتر رو نخورید. همیشه تعداد کد کمتر لزوما بهینه تر نیست.
قطعا اونی که یکبار به دیتابیس وصل میشه و عمل درج رو انجام میده سریعتر خواهد بود.
بذارید مثال دوم رو هم بزنم :
فرض کنید بخوایم بفهمیم که آیا یک شماره شناسایی (کلید) که توسط کاربر وارد شده است در جدولی با تعداد رکوردهای خیلی زیاد وجود داره یا نه. برای این کار دو کوئری زیر رو در نظر بگیرید :
1. استفاده از دستور EXISTS :
if(EXISTS(select UserID from TblUser where UserID = @userid))
2. استفاده از count :
select count(UserID) from TblUser where UserID = @userid
کوئری اول (دستور EXISTS ) به محض پیدا کردن رکورد، دیگه جستجو رو ادامه نمیده ولی کوئری دوم (دستور count) تا آخرین رکورد جدول رو پیمایش میکنه. این فقط یک مثال ساده بود.
نکته های زیادی وجود داره که باعث میشه سرعت برنامه افزایش پیدا کنه. مثلا بحث مدیریت کردن دیتایتبل و دیتاست که مستقیما از رم سیستم استفاده میکنن هست. خیلی از دوستان این اشیا رو به حال خودشون رها میکنن در حالیکه این رم به سیستم برگشت داده نمیشه (تا زمانیکه برنامه در حال اجرا هست) و خود ما باید بصورت دستی این رم رو آزاد کنیم. توجه نکردن به این مورد میتونه سرعت اجرای برنامه رو کم کنه. تصور کنید در 3 فرم متوالی قصد استفاده از شی دیتایتبل رو برای تعداد رکوردهای زیاد دارید و این دیتاتیبل ها مدیریت نشه. یه سیستم متوسط با رم 1 گیگ مگه چقدر رم خالی داره که تاوان کد نویسی اشتباه برنامه نویس رو بپردازه؟
خیلی از دوستان با dispose سعی در آزاد سازی حافظه دارند که این دستور در ازاد سازی رم سیستم ناتوان هست. برای این کار ما از کلاس GC (Grabber Collector) و از متد Collect اون کمک میگیریم. منظور از dt همون دیتاتیبل ما هست. با کد زیر حدود 90 درصد رم اختصاص داده شده برگشت داده میشه که بسیار موثر خواهد بود. اگر از دوستان کسی هست که کدی داشته باشه که بشه 100% رم تخصیص داده شده به دیتاتیبل رو پس گرفت، ممنون میشم اینجا قرار بده (من هرچی ور رفتم نتونستم چیزی رو پیدا کنم).
dt.Clear();
GC.Collect();
ضمن اینکه سبک برنامه نویسی هم بسیار موثر خواهد بود. استفاده از sp ها دارای سرعت بیشتری نسبت به روش های کدنویسی مستقیم در محیط ویژوال هست (حداقل در ADO.Net).
رعایت کردن مجموعه ای از این نکات میتونه یک برنامه بهینه رو ایجاد کنه.
من در زیر یکسری موارد رو برای افزایش سرعت عرض میکنم (هم سمت سی شارپ و هم سمت دیتابیس ):
1. کلید جدول رو که معمولا جستجوهای زیادی بر پایه اون انجام میشه، حتی الامکان int در نظر بگیرید. چراکه سرعت در جستجوی فیلدهای عددی نسبت به غیر عددی بیشتر هست.
2. کلید رو تا حد امکان ساده بگیرید و از ابرکلید(کلید ترکیبی) استفاده نکنید.
3. تا حد امکان از nvarchar استفاده نکنید چراکه دو برابر varchar فضای دیتابیس رو اشغال میکنن.
4. تا حد امکان جداول رو به گونه ای بسازید که نیاز به join های بی مورد بین جداول نباشه.
5. به غیر از فیلد کلید که خود sql بصورت اتومات یک clustered index براش میسازه. خودتون با توجه به نیاز پروزتون یک یا چند non clustered index برای جداولتون ایجاد کنید. البته در ایجاد تعداد زیاد این ایندکس ها زیاده روی نکنید. یکی از راه های تشخیص اینکه چه فیلدی رو non clusterd index قرار بدید اینه که روی چه فیلدی بیشتر عملیات جستجو رو انجام می دید. البته معیارهای دیگه ای هم هست که توصیه میکنم حتما درباره ایندکس ها مطالعه بفرمایید. چون ایندکس مناسب بر روی سرعت جستجوها (در تعداد رکوردهای زیاد) قدرت خودش رو به معرض نمایش میزاره.
6. استفاده از کوئری های بهینه (یک مثال رو در بالا نوشتم ).
7. سخت افزار قدرتمند. بدون شک شما برای محاسبه و جابه جایی اطلاعات به cpu و رم مناسب نیاز خواهید داشت.
گذشته از این موارد، طراحی درست و سبک کدنویسی ما میتونه اهمیت زیادی داشته باشه. مثلا استفاده از stored procedure ها در مقایسه با روش های معمولی کارآمدتر خواهد بود.