PDA

View Full Version : سوال: مشکل سرعت در sqlite



mr.siahatgar
شنبه 02 آذر 1398, 20:30 عصر
سلام من یه برنامه قبلا نوشته بودم با بانک اس کیو ال سرور
حالا بنا به دلایلی همون برنامه را با بانک sqlite نوشتم حالا مشکل اینجاست که سرعت اینزرت در sqlite خیلی کند هست مثلا اگر ده تا فایل میخوام اینزرت کنم در برنامه اولم چند ثانیه طول میکشه ولی در برنامه ای که با sqlit نوشتم چند دقیقه طول میکشه کسی راه حلی داره ضمنا با ویژوال 2019 کار میکنم




using (SQLiteConnection conn = new SQLiteConnection("Data Source=Db_Bank.sqlite;Version=3"))
{
conn.Open();
using (SQLiteCommand cmd = new SQLiteCommand(conn))
{
using (SQLiteTransaction tran = conn.BeginTransaction())
{
foreach (DataGridViewRow row in dataGridView1.Rows)
{
cmd.CommandText= "INSERT INTO MyTable VALUES(@Name, @Family, @Kod, @Mon)";
cmd.Parameters.AddWithValue("@Kod", row.Cells[0].Value);
cmd.Parameters.AddWithValue("@Per", row.Cells[1].Value);
cmd.Parameters.AddWithValue("@Sho", row.Cells[2].Value);
cmd.Parameters.AddWithValue("@Mon", row.Cells[3].Value);
cmd.ExecuteNonQuery();
}
tran.Commit();
}
}
conn.Close();
MessageBox.Show("records inserted");

the king
شنبه 02 آذر 1398, 21:16 عصر
سلام من یه برنامه قبلا نوشته بودم با بانک اس کیو ال سرور
حالا بنا به دلایلی همون برنامه را با بانک sqlite نوشتم حالا مشکل اینجاست که سرعت اینزرت در sqlite خیلی کند هست مثلا اگر ده تا فایل میخوام اینزرت کنم در برنامه اولم چند ثانیه طول میکشه ولی در برنامه ای که با sqlit نوشتم چند دقیقه طول میکشه کسی راه حلی داره ضمنا با ویژوال 2019 کار میکنم




using (SQLiteConnection conn = new SQLiteConnection("Data Source=Db_Bank.sqlite;Version=3"))
{
conn.Open();
using (SQLiteCommand cmd = new SQLiteCommand(conn))
{
using (SQLiteTransaction tran = conn.BeginTransaction())
{
foreach (DataGridViewRow row in dataGridView1.Rows)
{
cmd.CommandText= "INSERT INTO MyTable VALUES(@Name, @Family, @Kod, @Mon)";
cmd.Parameters.AddWithValue("@Kod", row.Cells[0].Value);
cmd.Parameters.AddWithValue("@Per", row.Cells[1].Value);
cmd.Parameters.AddWithValue("@Sho", row.Cells[2].Value);
cmd.Parameters.AddWithValue("@Mon", row.Cells[3].Value);
cmd.ExecuteNonQuery();
}
tran.Commit();
}
}
conn.Close();
MessageBox.Show("records inserted");



موقعی که یک Transaction رو Commit می کنید بصورت پیشفرض SQLite اونقدر صبر میکنه که داده ها از بافر سیستم فایل به روی سکتور های دیسک منتقل بشه تا خیالتون آسوده باشه که اگر جریان برق دیسک رفت داده ها قطعی ثبت شده باشن.
طبعا اینکار مکث ایجاد میکنه. میشه این انتظار روی Commit ها رو با یک تنظیم PRAGMA synchronous = OFF از بین برد ولی به قیمت از دست رفتن اون تضمین بقای اطلاعات تموم میشه.

mr.siahatgar
یک شنبه 03 آذر 1398, 07:18 صبح
سلام ممنون از شما سرعت یه کم بهتر شد ولی در حد قابل قبول نیست . شاید کدهام مشکل دارن؟

Mahmoud Zaad
یک شنبه 03 آذر 1398, 08:29 صبح
سلام
فایلهاتون چی هست حجمشون چقدره؟ بدون تراکنش هم تست کنید ببینید چقدر زمان می بره.

mr.siahatgar
یک شنبه 03 آذر 1398, 09:39 صبح
سلام
فایل های من بصورت نوت پد هستند که هر فایل حدود 250 خط داره . برنامه من میاد خط به خط اونها رو میخونه و اینزرت میکنه تو بانک . هر فایل حدود 30 تا 40 ثانیه و یا بیشتر طول میکشه در حالی که در بانک اس کیو ال سرور در صدمی از ثانیه طول میکشه . تعداد فایلها هم زیاد هست در نتیجه خیلی زمان میبره تا اینزرت بشه نزدیک 300 تا فایل هست که هر بار باید اینزرت بشه ضمنا یاداور کنم که هر خط نوت پد حدود 300 کارکتر داره که سه تا سه تا از هم جدا میشن . روش کار من هم اینجوری هست که هر سه تا کارکتر وارد یک ارایه و یا تکس باکس میکنم و بعد که خط کامل شد وارد بانک میکنم

رامین مرادی
یک شنبه 03 آذر 1398, 10:42 صبح
یه پیشنهاد. شما بجای اینکه یه دستور رو اجرا کنی بعد بری خط بدی رو بخونی و دوباره اینسرت کنی، یه بار کل خطها رو بخون و دستور اینسرتتو تشکیل بده و یه بار دستور رو اجرا کنید.

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

Mahmoud Zaad
یک شنبه 03 آذر 1398, 10:48 صبح
به نظرم ممکنه 3 تا مشکل وجود داشته باشه، یا از نحوه جداسازی کاراکترهاست، یا نحوه ثبت اطلاعات یا کند بودن تراکنش sqlite.
برای تست مورد اول کافیه کدهای درج در دیتابیس رو کامنت کنید و فقط زمان جداسازی کاراکترها رو تست کنید.
برای مورد دوم روش آقای مرادی در پست قبلی
برای مورد سوم هم که قبلا گفتم می تونید کدهای درج رو بدون تراکنش بنویسید و تست کنید.

mr.siahatgar
یک شنبه 03 آذر 1398, 12:06 عصر
یه پیشنهاد. شما بجای اینکه یه دستور رو اجرا کنی بعد بری خط بدی رو بخونی و دوباره اینسرت کنی، یه بار کل خطها رو بخون و دستور اینسرتتو تشکیل بده و یه بار دستور رو اجرا کنید.

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

mr.siahatgar
یک شنبه 03 آذر 1398, 12:10 عصر
به نظرم ممکنه 3 تا مشکل وجود داشته باشه، یا از نحوه جداسازی کاراکترهاست، یا نحوه ثبت اطلاعات یا کند بودن تراکنش sqlite.
برای تست مورد اول کافیه کدهای درج در دیتابیس رو کامنت کنید و فقط زمان جداسازی کاراکترها رو تست کنید.
برای مورد دوم روش آقای مرادی در پست قبلی
برای مورد سوم هم که قبلا گفتم می تونید کدهای درج رو بدون تراکنش بنویسید و تست کنید.

سلام
در مورد جداسازی تست کردم سریع انجام میشه
در مورد روش اقای مرادی هم توضیح دادم که نمیشه
در مورد تراکنش هم زیاد فرقی نکرد

mr.sirwan
یک شنبه 03 آذر 1398, 12:34 عصر
سلام
در مورد جداسازی تست کردم سریع انجام میشه
در مورد روش اقای مرادی هم توضیح دادم که نمیشه
در مورد تراکنش هم زیاد فرقی نکرد

منظورتون از نمیشه چیه؟ خب ساعت هر رکورد رو همراه همون رکورد ذخیره کنید مگه ساعت رو چجوری به رکورد اضافه میکنی؟
موقعیتت رو بیشتر توضیح بده تا دوستان بهتر راهنمایی کنن

mr.siahatgar
یک شنبه 03 آذر 1398, 12:43 عصر
منظورتون از نمیشه چیه؟ خب ساعت هر رکورد رو همراه همون رکورد ذخیره کنید مگه ساعت رو چجوری به رکورد اضافه میکنی؟
موقعیتت رو بیشتر توضیح بده تا دوستان بهتر راهنمایی کنن

دوست عزیز فرض کنید من یک فایل نوت پد دارم حاوی 5 خط مثل زیر
1398 08 01 00 254 352 462
1398 08 01 01 255 355 425
1398 08 01 02 269 358 458
1398 08 01 03 256 322 456
1398 08 01 04 265 356 489
حالا با یک حلقه میاد خط اول را میخونه و 1398 درون تکس باکس 1 وعدد 08 را درون تکس باکس 2 وعدد 01 را درون تکس باکس 3 وعدد 00 را درون تکس باکس 4 وعدد 254 را درون تکس باکس 5 وعدد 352 را درون تکس باکس 6 و در اخر عدد 425 را درون تکس باکس 7 قرار میده بعد دستور اینزرت تکس باکس ها میبره درون بانک و بعد خط دوم میخونه
خب اگه قرار باشه خط دوم هم همزمان بخونه باید تکس باکس ها اضافه کنم و خط دوم درون تکس باکسهای جدید بزارم و دوباره یه دستور اینزرت بنویسم و تکس باکسهای جدید را ببره توی بانک
اینجوری که خیلی بیشتر میشه و دیگه درون حلقه هم نمیشه بزارم . شما راه حلتون چیه چجوری با یه دستور اینزرت اونها را ببرم توی بانک و ضمنا یاداور بشم من قبل از اینکه برم توی بانک باید یک سری عملیات هم روی اون انجام بدم بعد وارد بانک کنم

mmbguide
یک شنبه 03 آذر 1398, 12:53 عصر
به نظرم اگر نیازی به Text box نداری بیا آرایه ای از یک Structure. بساز و تمام خطوط رو به تفکیک مورد نظر در او ذخیره کن و بعد عملیات insert. یا در هربار خواندن خطوط، مقادیر رو براحتی در یک آرایه نگهداری کن (با استفاده از split) و بعد insert و الی آخر.
به نظرم از text box صرفا بخاطر تفکیک مقادیر استفاده نکن

Mahmoud Zaad
یک شنبه 03 آذر 1398, 13:30 عصر
روش خوندن فایل متنی چطوره؟

برای جداسازی، همانطور که دوستمون گفتن نیازی به تکست باکس نیست.
شما میتونید اطلاعات هر ردیف رو به شکل زیر جداسازی کنید:
string[] _split=_str.Split(' ');
string _one=_split[0];
string _two=_split[1];
//...
بعد متغیرهای _one و _two و ... رو توی دیتابیس ذخیره کنید

the king
یک شنبه 03 آذر 1398, 13:48 عصر
اگر من میخواستم همچین سوالی رو مطرح کنم یک فایل نمونه با دو تا سطر داده ارائه میکردم که بشه برای فرمتش راهکار ارائه کرد.
این مثال 1398 08 01 00 254 352 462 که نوشتید مشخص میکنه که بین اعداد کاراکتر فاصله هست ولی نه با اون مشخصات "هر خط نوت پد حدود 300 کارکتر" جور در میاد و نه تصوری از نحوه درج مقادیر در (@Name, @Family, @Kod, @Mon) میده.
با توصیفی که شما از فایل های متنی تون میکنید در بدترین شرایط که Unicode باشن حداکثر 150 کیلوبایت حجم دارن، زیاد نیست، نیازی نیست که بصورت Stream و کاراکتر به کاراکتر تفسیرشون کنیم.
میشه با System.IO.File.ReadAllLines یکجا در آرایه متنی فراخوانی شون کرد و بعد در هر سطر با (" ")string.Split مقادیر رو تفکیک کرد. با int.Parse هم که رشته ها به مقدار عددی تبدیل میشن.
مادامی که تصور ما از محتویات سطر ها ناقص باشه سخته بشه برای نوشتن یک روتین کارآمد کمکی کرد.

mr.siahatgar
یک شنبه 03 آذر 1398, 17:00 عصر
اگر من میخواستم همچین سوالی رو مطرح کنم یک فایل نمونه با دو تا سطر داده ارائه میکردم که بشه برای فرمتش راهکار ارائه کرد.
این مثال 1398 08 01 00 254 352 462 که نوشتید مشخص میکنه که بین اعداد کاراکتر فاصله هست ولی نه با اون مشخصات "هر خط نوت پد حدود 300 کارکتر" جور در میاد و نه تصوری از نحوه درج مقادیر در (@Name, @Family, @Kod, @Mon) میده.
با توصیفی که شما از فایل های متنی تون میکنید در بدترین شرایط که Unicode باشن حداکثر 150 کیلوبایت حجم دارن، زیاد نیست، نیازی نیست که بصورت Stream و کاراکتر به کاراکتر تفسیرشون کنیم.
میشه با System.IO.File.ReadAllLines یکجا در آرایه متنی فراخوانی شون کرد و بعد در هر سطر با (" ")string.Split مقادیر رو تفکیک کرد. با int.Parse هم که رشته ها به مقدار عددی تبدیل میشن.
مادامی که تصور ما از محتویات سطر ها ناقص باشه سخته بشه برای نوشتن یک روتین کارآمد کمکی کرد.

بله حق با شماست من باید فایل نمونه قرار دهم ولی این نکته رو بگم که من الا با جدا کردن و داخل تکس باکس قرار دادن مشکلی ندارم چون سریع در میلی ثانیه این کار انجام میشه مشکل من فقط در هنگام اینزرت کردن ان هست مه زیاد طول میکشه در مورد فایل هم باید بگم که متاسفانه من ناچارم خط به خط بخونم زیرا روی انها عملیاتهای انجام میدم و بعد در تکس باکس قرار میدم و ضمنا بعضی کارکترهایم بستگی داره که خط قبلش چی باشه و براین اساس اون کارکتر ذخیر میشه یا نمیشود . بگذریم در کل مشکل من فقط در قسمت اینزرت هست بنظر شما اگر بخوام از ارایه اینزرت کنم نسبت به تکس باکس از سرعت قابل توجهی برخوردار میشه یعنی اینقدر سرعتش تغییر میکنه که احساش بشه ؟

the king
یک شنبه 03 آذر 1398, 18:47 عصر
با آزمایشی که کردم بین صد هزار تا دویست هزار رکورد در ثانیه داخل جدول درج کرد. خوبه دیگه :لبخند:

151014

پروژه #C اش ضمیمه گردید :

151010
151011
151012
151013

mr.siahatgar
دوشنبه 04 آذر 1398, 07:32 صبح
با آزمایشی که کردم بین صد هزار تا دویست هزار رکورد در ثانیه داخل جدول درج کرد. خوبه دیگه :لبخند:

151014

پروژه #C اش ضمیمه گردید :

151010
151011
151012
151013


سلام موقع لود فرم این پیام خطا میده
151015

the king
دوشنبه 04 آذر 1398, 08:51 صبح
سلام موقع لود فرم این پیام خطا میده
151015
لطفا قبل از اون سطر در listBox1_DrawItem یک شرط خروج قرار بدید :


if ((e.Index < 0) || (e.Index >= listBox1.Items.Count))
{
return;
}
var item = (object[])listBox1.Items[e.Index];

mr.siahatgar
دوشنبه 04 آذر 1398, 10:09 صبح
لطفا قبل از اون سطر در listBox1_DrawItem یک شرط خروج قرار بدید :


if ((e.Index < 0) || (e.Index >= listBox1.Items.Count))
{
return;
}
var item = (object[])listBox1.Items[e.Index];



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

the king
دوشنبه 04 آذر 1398, 10:17 صبح
سلام ممنون از شما ولی من اجرا کردم وقتی توی جدول ساخته شده نگاه کردم فقط سرستون ها بود و هیچ داده ای وارد نشده بود

tran.Commit(); رو در انتهای بلوک اش قرار بدید. من حذفش کردم ببینم چقدر تاثیر داره، دیدم وقتی بعد درج همه رکورد ها انجام میشه مکث محسوسی نداره.

mr.siahatgar
جمعه 08 آذر 1398, 09:09 صبح
سلام دوستان گرامی
من بعد از اینکه فایل ها را وارد تکس باکس کردم و عملیات های لازم را بر روی انها انجام دادم ، دادا ها را وارد ارایه کردم و از ارایه اینزرت کردم به جدول و مشکل حل شد . سرعتش هم خیلی عالی شد

the king
جمعه 08 آذر 1398, 10:53 صبح
سلام دوستان گرامی
من بعد از اینکه فایل ها را وارد تکس باکس کردم و عملیات های لازم را بر روی انها انجام دادم ، دادا ها را وارد ارایه کردم و از ارایه اینزرت کردم به جدول و مشکل حل شد . سرعتش هم خیلی عالی شد
چه عالی. تفاوت اساسی بین کد قبلی و جدید که نوشتید چی بود؟ یعنی با تفسیر خودتون چی چیزی در کد قبلی منجر به کند شدن درج ها بود؟

mr.siahatgar
شنبه 09 آذر 1398, 16:54 عصر
چه عالی. تفاوت اساسی بین کد قبلی و جدید که نوشتید چی بود؟ یعنی با تفسیر خودتون چی چیزی در کد قبلی منجر به کند شدن درج ها بود؟

سلام دوست گرامی سری اول من مستقیم از تکس باکس میریختم تو بانک
اما در سری دوم اومدم بعد از تکس باکس ریختم توی ارایه و بعد از ارایه ریختم توی بانک
حالا جه عاملی دقیقا باعث کندی میشد نمیدونم ولی گویا از تکس باکس مستیم ریختم توی بانک کند میشد
در سری دوم با وجودی که اول از تکس باکس انتقال میدادم به ارایه ( که حدس میزدم خب با اینکار زمان بیشتری میبره) و بعد از ارایه ریختم توی بانک که برخلاف تصورم خیلی سرعت عالی شد و در حد شاید کمتر از چند میلی ثانیه شد